═══ 1. Title page ═══ 32 bits OS/2 device driver and IFS support MWDD32 VERSION 1.70 Copyright (C) Matthieu WILLM 1995, 1996, 1997 (willm@ibm.net) ═══ 2. Copyright information ═══ 32 bits OS/2 device driver and IFS support. Provides 32 bits kernel services (DevHelp) and utility functions to 32 bits OS/2 ring 0 code (device drivers and installable file system drivers). Copyright (C) 1995, 1996, 1997 Matthieu WILLM This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You 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. This package contains GNU GPL copyrighted code whose owners are :  Linus Torvalds and Lars Wirsenius (list of files)  Eberhard Mattes (list of files)  Holger Veit (list of files) Note: If you want to use my own parts (parts that do not contain code from others) but not under the GNU GPL you must contact me and sign an agreement with me. ═══ 3. 32 bits ring 0 considerations ═══  stack based pointers vs FLAT based pointers  converting 16:16 pointers to FLAT pointers ═══ 3.1. stack based pointers vs FLAT based pointers ═══ Under OS/2, at ring 0 SS is NOT equal to DS. With Visualage C++ you MUST use /Gr+ /Rn compiler options. SS!=DS also means that you cannot safely use or pass SS based addresses to functions. SS based addresses are for instance addresses of automatic data (local variables and function parameters). To convert SS based addresses to DS based addresses you must use the __StackToFlat() routine, as in the following example : ILLEGAL CODE IN OS/2 KERNEL MODE (produces a trap D) : int my_sub(int *a) { /* * a is treated as a FLAT based address by the compiler */ } int my_routine(void) { int a; /* * In the following statement &a is a STACK based address */ return my_sub(&a); } WORKING CODE IN OS/2 KERNEL MODE : int my_sub(int *a) { /* * a is treated as a FLAT based address by the compiler */ } int my_routine(void) { int a; /* * Here the correct FLAT based value of &a is passed to my_sub() */ return my_sub(__StackToFlat(&a)); } ═══ 3.2. converting 16:16 pointers to FLAT pointers ═══ Because the PDD and IFS interfaces are still 16 bits, many parameters of routines (strategy routines for PDD, IFS entry points, DevHelp) contain 16:16 addresses. THEY CANNOT BE USED DIRECTLY : YOU MUST CONVERT THEM TO 0:32 FIRST. To do this, use DevHlp32_VirtToLin, like in the following example : #define INCL_DOS #define INCL_DOSERRORS #define INCL_NOPMAPI #include #include #include #include #include /* * struct fs32_findnext_parms { * unsigned short flags; * unsigned short level; * PTR16 pcMatch; * unsigned short cbData; * PTR16 pData; * PTR16 pfsfsd; * PTR16 pfsfsi; * }; */ int FS32ENTRY fs32_findnext(struct fs32_findnext_parms *parms) { struct fsfsi32 *pfsfsi; struct fsfsd32 *pfsfsd; char *pData; unsigned short *pcMatch; int rc; /* * parms is passed as a STACK based address by fs_findnext.asm */ parms = __StackToFlat(parms); /* * We first convert all 16:16 pointers to 0:32 */ if ((rc = DevHlp32_VirtToLin(parms->pfsfsi, __StackToFlat(&pfsfsi))) == NO_ERROR) { if ((rc = DevHlp32_VirtToLin(parms->pfsfsd, __StackToFlat(&pfsfsd))) == NO_ERROR) { if ((rc = DevHlp32_VirtToLin(parms->pData, __StackToFlat(&pData))) == NO_ERROR) { if ((rc = DevHlp32_VirtToLin(parms->pcMatch, __StackToFlat(&pcMatch))) == NO_ERROR) { /* * Insert your code here ... */ rc = NO_ERROR; } } } } return rc; } Note: NEVER USE THE THUNKING FACILITIES OF VISUALAGE C++ OR OTHER COMPILERS : THEY USE A METHOD THAT SIMPLY DOES NOT WORK AT RING 0. Especially NEVER use _Seg16, _Far16 and related keywords. ALL THUNKS MUST BE DONE MANUALLY. Look at the sources of mwdd32.sys for examples of manual 16->32 and 32->16 thunks. ═══ 4. The DEVHLP32 interface ═══ This chapter describes the 32 bits DevHelp interfaces provided by mwdd32.sys. To use them from C code, you must include the following files :  os2/types.h  os2/devhlp32.h This document is only intented to describe the 32 bits version of the DevHelp calls, it does NOT replace the DDK's Physical Device Driver Reference. Please refer to that document for a more complete description of the DevHelp calls. Note:  Unless otherwise specified, ALL pointers are 32 bits FLAT pointers.  Unless ohterwise specified, ALL DevHlp32 routines follow the 32 bits SYSTEM calling convention (parameters pushed from right to left, caller cleans up the stack, EBP ESI EDI EBX and all segment registers are preserved, other are not) List of DevHlp32 routines :  DevHlp32_VMLock  DevHlp32_VMUnlock  DevHlp32_ProcBlock  DevHlp32_ProcRun  DevHlp32_VMAlloc  DevHlp32_VMFree  DevHlp32_VirtToLin  DevHlp32_InternalError  DevHlp32_SaveMessage  DevHlp32_LinToPageList  DevHlp32_Yield  DevHlp32_GetInfoSegs  DevHlp32_setIRQ  DevHlp32_UnSetIRQ  DevHlp32_EOI  DevHlp32_PageListToLin  DevHlp32_AllocGDTSelector  DevHlp32_FreeGDTSelector  DevHlp32_AttachDD  DevHlp32_GetDosVar  DevHlp32_OpenEventSem  DevHlp32_CloseEventSem  DevHlp32_ResetEventSem  DevHlp32_PostEventSem  DevHlp32_VerifyAccess ═══ 4.1. DevHlp32_VMLock ═══ Locks a memory region in physical memory int DH32ENTRY DevHlp32_VMLock( unsigned long flags, void *addr, unsigned long length, void *pPageList, void *pLockHandle, unsigned long *pPageListCount ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ Parameters description : ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long flags │input │DevHlp_VMAlloc flags (cf Physical Device │ │ │ │Driver Reference). │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │void *addr │input │Address of the region to lock. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long length│input │length of region to lock. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │void *pPageList │in/out │Pointer to a location where VMLock will store│ │ │ │the list of locked pages. Can be 0. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │void *lock │in/out │Pointer to a 12 bytes region to store the │ │ │ │lock handle. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long │in/out │Pointer to an unsigned long integer where │ │*pPageListCount │ │VMLock will place the count of pages locked. │ │ │ │MUST be a valid pointer. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.2. DevHlp32_VMUnlock ═══ Unlocks a memory region locked by DevHlp32_VMLock int DH32ENTRY DevHlp32_VMUnlock( void *pLockHandle ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │void *pLockHandle │input │Pointer to the 12 bytes lock handle filled in│ │ │ │by DevHlp32_VMLock. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.3. DevHlp32_ProcBlock ═══ Blocks the current thread. int DH32ENTRY DevHlp32_ProcBlock( unsigned long eventid, long timeout, short interruptible ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long │input │Arbitrary value used by the OS/2 kernel as a │ │eventid │ │block ID. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │long timeout │input │Duration of blocking. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │short interruptible │input │Whether the blocking is interruptible by │ │ │ │CTRL+C or not. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.4. DevHlp32_ProcRun ═══ Puts all threads blocked on a particular event in the READY state. int DH32ENTRY DevHlp32_ProcRun( unsigned long eventid ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ Yes │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long │input │Same value as passed to DevHlp32_ProckBlock. │ │eventid │ │ │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.5. DevHlp32_VMAlloc ═══ Page granular memory allocation. int DH32ENTRY DevHlp32_VMAlloc( unsigned long Length, unsigned long PhysAddr, unsigned long Flags, void **LinAddr ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long Length│input │Size of memory block to allocate. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long │input │Physical address of region to map (if any), │ │PhysAddr │ │-1 otherwise. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long Flags │input │Allocation flags (cf Physical Device Driver │ │ │ │Reference) │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │void **LinAddr │in/out │Pointer to a void * where VMAlloc will store │ │ │ │the pointer to the allocated block of memory.│ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.6. DevHlp32_VMFree ═══ Frees memory previously allocated with DevHlp32_VMAlloc. int _Optlink DevHlp32_VMFree( void *addr /* eax */ ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │void *addr │input │Pointer to the memory block to free. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.7. DevHlp32_VirtToLin ═══ Converts a virtual 16:16 address to a FLAT 0:32 address. int DH32ENTRY DevHlp32_VirtToLin( PTR16 virt, void **plin ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ Yes │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │PTR16 virt │input │Virtual 16:16 address to convert. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │void **plin │in/out │Pointer to a void * where VirtToLin will │ │ │ │store the returned 0:32 address. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.8. DevHlp32_InternalError ═══ Initiates the kernel panic procedure (abrupt system halt). void DH32ENTRY DevHlp32_InternalError( char *msg, int len ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │char *msg │input │Error message to display on the kernel trap │ │ │ │screen. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int len │input │Message length, including terminating \0. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.9. DevHlp32_SaveMessage ═══ Displays a message on the screen at bootup. int DH32ENTRY DevHlp32_SaveMessage( char *msg, int len ); Execution context : Can be called from 32 bits ring 0 code as long as the OS/2 boot procedure is not finished.  for a BASEDEV, it can be called during 32 bits ring 0 INIT time (drv32_init_base() in the sample skeleton).  for an IFS, it can be called during 32 bits ring 0 INIT time (fs32_init() in the sample skeleton). ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │char *msg │input │Message to display on the screen. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int len │input │Message length, including terminating \0. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.10. DevHlp32_LinToPageList ═══ Returns the page list mapping a given memory region. int DH32ENTRY DevHlp32_LinToPageList( void *lin, unsigned long size, struct PageList *pages, unsigned long *nr_pages ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │void *lin │input │Address of memory region to map. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long size │input │Size of memory region to map. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │struct PageList │in/out │Pointer to a PageList structure array where │ │*pages │ │LiToPageLin will store the page information. │ │ │ │It must be large enough. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long │in/out │Pointer to an unsigned integer where │ │*nr_pages │ │LinToPageList will store the number of pages │ │ │ │returned. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.11. DevHlp32_Yield ═══ Gives up the CPU and let higher priority threads to run. void DH32ENTRY DevHlp32_Yield(void); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.12. DevHlp32_GetInfoSegs ═══ Retrieves FLAT pointers to the Global and Local information segments. Note: This call has no 16 bits DevHelp equivalent. It has a more simpler and faster implementation that calling DevHlp_GetDOSVar and thunking the result : it directly retrieves values from the System Anchor Segment. int DH32ENTRY DevHlp32_GetInfoSegs( struct InfoSegGDT **ppSysInfoSeg, /* ebp + 8 */ struct InfoSegLDT **ppLocInfoSeg /* ebp + 12 */ ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │struct InfoSegGDT │in/out │Pointer to a double word where will be stored│ │**ppSysInfoSeg │ │the global information segment linear │ │ │ │address. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │struct InfoSegLDT │in/out │Pointer to a double word where will be stored│ │**ppLocInfoSeg │ │the local information segment linear address.│ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.13. DevHlp32_setIRQ ═══ Sets a hardware interrupt vector. int DH32ENTRY DevHlp32_setIRQ( unsigned short offset_irq, /* ebp + 8 */ unsigned short interrupt_level, /* ebp + 12 */ unsigned short sharing_flag, /* ebp + 16 */ unsigned short data16_segment /* ebp + 20 */ ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short │input │offset to the 16:16 interrupt service routine│ │offset_irq │ │(see note below). │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short │input │hardware interrupt to be serviced. │ │interrupt_level │ │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short │input │whether the IRQ is to be shared or not. │ │sharing_flag │ │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short │input │selector of the device driver 16 bits data │ │data16_segment │ │segment (the one containing the device │ │ │ │header). │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ Note: The Interrupt handler set by DevHlp32_setIRQ must be a 16:16 entry point. To implement a 32 bits interrupt handler, simply make a small 16:16 stub that does a far call to the 32 bits handler. You can find an example in ./skeleton/basedev : drv32_stub_irq.asm contains the 16:16 stub drv32_irq.c contains the 32 bits interrupt handler drv32_init_base.c contains the call to DevHlp32_setIRQ ═══ 4.14. DevHlp32_UnSetIRQ ═══ Frees a hardware interrupt vector. int DH32ENTRY DevHlp32_UnSetIRQ( unsigned short interrupt_level, /* ebp + 8 */ unsigned short data16_segment /* ebp + 12 */ ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ Yes │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short │input │hardware interrupt to be serviced. │ │interrupt_level │ │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short │input │selector of the device driver 16 bits data │ │data16_segment │ │segment (the one containing the device │ │ │ │header). │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.15. DevHlp32_EOI ═══ Sends EOI to the interrupt controller. Note: This routine has _Optlink linkage for performance reasons. int DH32ENTRY2 DevHlp32_EOI( unsigned short interrupt_level /* ax */ ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ No │ Yes │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short │input │hardware interrupt to be serviced. │ │interrupt_level │ │ │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.16. DevHlp32_PageListToLin ═══ Maps physical pages to a linear address. int DH32ENTRY DevHlp32_PageListToLin( unsigned long size, /* ebp + 8 */ struct PageList *pPageList, /* ebp + 12 */ void **pLin /* ebp + 16 */ ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ Yes │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long size │input │Count of bytes to be mapped (it must not │ │ │ │exceed 64 Kb) │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │struct PageList │input │List of pages to be mapped │ │*pPageList │ │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │void **pLin │in/out │Pointer to a void * where PageListToLin will │ │ │ │store the linear address obtained. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.17. DevHlp32_AllocGDTSelector ═══ Allocates a set of GDT selectors. int DH32ENTRY DevHlp32_AllocGDTSelector( unsigned short *psel, int count ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short *psel│in/out │Pointer to an array of unsigned short where │ │ │ │AllocGDTSelector will put the allocated │ │ │ │selector values. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int count │input │Number of GDT selectors to be allocated │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.18. DevHlp32_FreeGDTSelector ═══ Frees a GDT selector previously allocated with DevHlp32_AllocGDTSelector. int DH32ENTRY2 DevHlp32_FreeGDTSelector( unsigned short sel /* ax */ ); Note: This routine has _Optlink linkage. Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short sel │input │GDT selector to be freed. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.19. DevHlp32_AttachDD ═══ Retrieves another device driver's IDC entry point. int DH32ENTRY DevHlp32_AttachDD( char *ddname, /* ebp + 8 */ struct ddtable *table /* ebp + 12 */ ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │char *ddname │input │Name of device driver. Must be less that 9 │ │ │ │characters including trailing NULL. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │struct ddtable │in/out │Pointer to a structure where AttachDD will │ │*table │ │put the IDC entry point information. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ Warning: The name must match EXACTLY the name of the driver present in its header, INCLUDING trailing spaces if any. ═══ 4.20. DevHlp32_GetDosVar ═══ Gets the address of a kernel variable. extern int DH32ENTRY DevHlp32_GetDosVar( int index, /* ebp + 8 */ PTR16 *value, /* ebp + 12 */ int member /* ebp + 16 */ ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int index │input │Index of the variable to be retrieved. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │ PTR16 *value │in/out │Pointer to a PTR16 where GetDosVar will put │ │ │ │the address of the kernel variable. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int member │input │Member to be retrieved for index 14 and 16, 0│ │ │ │otherwise. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.21. DevHlp32_OpenEventSem ═══ Opens a 32 bits shared event semaphore. int DH32ENTRY DevHlp32_OpenEventSem( unsigned long handle /* ebp + 8 */ ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long handle│input │handle of the 32 bits semaphore to be opened.│ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.22. DevHlp32_CloseEventSem ═══ Closes a 32 bits shared event semaphore. int DH32ENTRY DevHlp32_CloseEventSem( unsigned long handle /* ebp + 8 */ ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long handle│input │handle of the 32 bits semaphore to be closed.│ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.23. DevHlp32_ResetEventSem ═══ Resets a 32 bits shared event semaphore. int DH32ENTRY DevHlp32_ResetEventSem( unsigned long handle, /* ebp + 8 */ int *nposts /* ebp + 12 */ ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long handle│input │handle of the 32 bits semaphore to be reset. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int *nposts │in/out │pointer to an integer where ResetEventSem │ │ │ │will store the semaphore post count before │ │ │ │reset. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.24. DevHlp32_PostEventSem ═══ Posts a 32 bits shared event semaphore. int DH32ENTRY DevHlp32_PostEventSem( unsigned long handle /* ebp + 8 */ ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long handle│input │handle of the 32 bits semaphore to be posted.│ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 4.25. DevHlp32_VerifyAccess ═══ Performs access control on a 16:16 pointer. int DH32ENTRY DevHlp32_VerifyAccess( PTR16 address, /* ebp + 8 */ unsigned short size, /* ebp + 12 */ int flags /* ebp + 16 */ ); Execution context : ┌──────────┬──────────┐ │ Task │Interrupt │ ├──────────┼──────────┤ │ Yes │ No │ └──────────┴──────────┘ ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │PTR16 address │input │16:16 address to be verified. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short size │input │size of the aera to be verified. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int flags │input │type of access control to perform │ │ │ │(readonly/readwrite) │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 5. The FSH32 interface ═══ This chapter describes the 32 bits FSHelp interfaces provided by fsh32.lib. To use them from C code, you must include the following files :  os2/types.h  os2/devhlp32.h  os2/fsh32.h This document is only intented to describe the 32 bits version of the FSHelp calls, it does NOT replace the Installable File Systems for OS/2 version 3 document. Please refer to that document for a more complete description of the FSHelp calls. Note:  Unless otherwise specified, ALL pointers are 32 bits FLAT pointers.  Unless ohterwise specified, ALL fsh32 routines follow the 32 bits SYSTEM calling convention (parameters pushed from right to left, caller cleans up the stack, EBP ESI EDI EBX and all segment registers are preserved, other are not) List of fsh32 routines :  fsh32_dovolio  fsh32_segalloc  fsh32_findduphvpb  fsh32_forcenoswap  fsh32_getvolparm  fsh32_addshare  fsh32_removeshare  fsh32_setvolume ═══ 5.1. fsh32_dovolio ═══ Issues a sector based I/O operation. int FSH32ENTRY fsh32_dovolio( int operation, /* ebp + 8 */ int fAllowed, /* ebp + 12 */ int hVPB, /* ebp + 16 */ void *pData, /* ebp + 20 */ unsigned long *pcSec, /* ebp + 24 */ unsigned long iSec /* ebp + 28 */ ); Parameters description : ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int operation │input │type of I/O (cf Installable File Systems for │ │ │ │OS/2 version 3). │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int fAllowed │input │Allowed actions the kernel can take in case │ │ │ │of hard error. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int hVPB │input │Volume Parameter Block handle. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │void *pData │in/out │Transfert address. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long *pcSec│in/out │Pointer to a double word containing the │ │ │ │number of sectors to transfer. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int iSec │input │Sector number of first sector to transfer. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 5.2. fsh32_segalloc ═══ Allocates a 16 bits segment. int FSH32ENTRY fsh32_segalloc( int flags, /* ebp + 8 */ int length, /* ebp + 12 */ unsigned short *pSel /* ebp + 16 */ ); Parameters description : ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int flags │input │Allocation flags (cf Installable File Systems│ │ │ │for OS/2 version 3). │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int length │input │Length of segment to be allocated. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short *pSel│in/out │Pointer to a word where will be stored the │ │ │ │segment selector. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 5.3. fsh32_findduphvpb ═══ Looks for a duplicate volume parameter block of the current volume parameter block. int FSH32ENTRY fsh32_findduphvpb( unsigned short hVPB, /* ebp + 8 */ unsigned short *phVPB /* ebp + 12 */ ); Parameters description : ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short hVPB │input │Volume parameter block handle. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short │in/out │Pointer ot a word where will be stored the │ │*phVPB │ │duplicate hVPB, if any. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 5.4. fsh32_forcenoswap ═══ Permanently locks a 16 bits segment of the IFS load image into physical memory. Note: the linkage convention is FSHENTRY2 (Visualage C++ _Optlink). int FSH32ENTRY2 fsh32_forcenoswap( unsigned short selector ); Parameters description : ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short │input │selector of the 16 bits segment to lock. │ │selector │ │ │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 5.5. fsh32_getvolparm ═══ Retrieves the volume parameter block (vpfsi and vpfsd) from a volume parameter block handle (hVPB). int FSH32ENTRY fsh32_getvolparm( unsigned short hVPB, PTR16 *ppvpfsi, PTR16 *ppvpfsd ); ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short hVPB │input │handle of volume parameter block │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │PTR16 *ppvpfsi │in/out │FLAT pointer to a double word where the │ │ │ │kernel will store the 16:16 pointer to the │ │ │ │vpfsi │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │PTR16 *ppvpfsd │in/out │FLAT pointer to a double word where the │ │ │ │kernel will store the 16:16 pointer to the │ │ │ │vpfsd │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 5.6. fsh32_addshare ═══ Adds a name to the sharing set. extern int FSH32ENTRY fsh32_addshare( PTR16 pName, unsigned short mode, unsigned short hVPB, unsigned long *phShare ); ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │PTR16 pName │input │16:16 pointer to the name to be added. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short mode │input │Requested sharing mode (OPEN_SHARE_*) and │ │ │ │access mode (OPEN_ACCESS_*). │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long │in/out │Pointer to a double word where the kernel │ │*phShare │ │will store the share handle. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 5.7. fsh32_removeshare ═══ Removes a name from the sharing set. Note: the linkage convention is FSHENTRY2 (Visualage C++ _Optlink). extern void FSH32ENTRY2 fsh32_removeshare( unsigned long hShare /* eax*/ ); ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long hShare│input │Share handle (returned by fsh32_addshare). │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 5.8. fsh32_setvolume ═══ Forces a specified volume to be mounted on its drive. Note: the linkage convention is FSHENTRY2 (Visualage C++ _Optlink). extern int FSH32ENTRY2 fsh32_setvolume( unsigned short hVPB, /* ax */ unsigned long fControl /* edx */ ); ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned short hVPB │input │Volume parameter block handle of volume. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │unsigned long │input │hard error daemon popup flag. │ │fControl │ │ │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 6. Kernel utility functions ═══ This chapter describes the 32 bits kernel utility functions provided by mwdd32.sys. These functions include some ansi C and some POSIX useful functions, callable from ring 0 OS/2 kernel code. To use them from C code, you must include the following files :  os2/types.h  os2/devhlp32.h This document is only intented to describe the OS/2 kernel version of these calls, it does NOT replace an ANSI C or POSIX programming manual. Note:  Unless otherwise specified, ALL pointers are 32 bits FLAT pointers.  Unless ohterwise specified, ALL utility functions follow the 32 bits SYSTEM calling convention (parameters pushed from right to left, caller cleans up the stack, EBP ESI EDI EBX and all segment registers are preserved, other are not) List of utility functions :  vsprintf  strtoul  atol  strupr  strpbrk  fnmatch  strtol  sec32_attach_ses ═══ 6.1. vsprintf ═══ Issues a formatted output to a buffer. int DH32ENTRY vsprintf ( char *buffer, const char *format, va_list arg_ptr ); Parameters description : ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │char *buffer │in/out │buffer in which will be put the formatted │ │ │ │string. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │const char *format │input │Format string (cf an ANSI C programming │ │ │ │manual for a description of its contents) │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │va_list arg_ptr │input │Pointer to a variable size list of arguments │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 6.2. strtoul ═══ Converts a character string to an unsigned long integer. unsigned long DH32ENTRY strtoul ( const char *string, char **end_ptr, int radix ); Parameters description : ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │const char *string │input │String to be converted │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │char **end_ptr │in/out │Filled with the pointer to the first │ │ │ │character not converted │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int radix │input │Base in which the number should be │ │ │ │interpreted (auto (0), 8, 10, 16) │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 6.3. atol ═══ Converts the textual representation of a long integer to a long integer. long DH32ENTRY atol (const char *string); Parameters description : ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │const char *string │input │String to be converted. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 6.4. strupr ═══ Uppercases a string. char *strupr(const char *string); Parameters description : ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │const char *string │in/out │On input : string to be uppercased. On ouput │ │ │ │: uppercased string. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 6.5. strpbrk ═══ Return a pointer to the first occurrence in the string pointed to by string1 of a character of the string pointed to by string2. char * DH32ENTRY strpbrk (const char *string1, const char *string2); Parameters description : ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │const char *string1 │input │string to search for characters. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │const char *string2 │input │string containig characters to look for. │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 6.6. fnmatch ═══ Matches a file name using wildcards (OS/2 or POSIX semantics) Note: This call is a good replacement of FSH_WILDMATCH. int DH32ENTRY fnmatch (const char *mask, const char *name, int flags); Parameters description : ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │const char *mask │input │string containing wildcard. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │const char *name │input │file name to be matched by mask. │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int flags │input │flags to modify matching semantics. │ │ │ │(_FNM_OS2, FNM_POSIX, _FNM_IGNORECASE) │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 6.7. strtol ═══ Converts a character string to a long integer. long DH32ENTRY strtol ( const char *string, char **end_ptr, int radix ); Parameters description : ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │const char *string │input │String to be converted │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │char **end_ptr │in/out │Filled with the pointer to the first │ │ │ │character not converted │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │int radix │input │Base in which the number should be │ │ │ │interpreted (auto (0), 8, 10, 16) │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 6.8. sec32_attach_ses ═══ Attaches to sesdd32.sys and retieves sesdd32.sys's security entry points. int DH32ENTRY sec32_attach_ses( void *SecHlp ); Parameters description : ┌────────────────────┬──────────┬─────────────────────────────────────────────┐ │Parameter type │Input │Description │ │ │Output │ │ ├────────────────────┼──────────┼─────────────────────────────────────────────┤ │void *SecHlp │in/out │Pointer to a SecurityHelpers structure that │ │ │ │will be filled with sesdd32.sys's SecHlp │ │ │ │entry points │ └────────────────────┴──────────┴─────────────────────────────────────────────┘ ═══ 7. Sample 32 bits device drivers ═══ This chapter describes the sample device drivers included in this package. 1. 32 bits regular (DEVICE) device driver 2. 32 bits base (BASEDEV) device driver 3. 32 bits Installable File System (IFS) driver 4. 32 bits OS/2 Security Enabling Services (SES) driver Note: The 32 bits version of my Linux ext2fs IFS is now available and is a good example of a full featured 32 bits IFS, which uses mwdd32.sys services. It can be found at : ftp://ftp.leo.org/pub/comp/os/os2/drivers/ifs/ext2_200.zip ftp://sunsite.unc.edu/pub/Linux/system/Filesystems/ext2/ext2_200.zip ═══ 7.1. 32 bits regular (DEVICE) device driver ═══ Location: ·/32bits/ext2-os2/skeleton/device Device driver initialization: Regular device drivers initialize at ring 3. Because at this time the FLAT code segment is unreachable (ring 0), the driver cannot do a far call to its 32 bits initialization routine. To achieve 32 bits initialization, a small 16 bits routine called at INIT time does the following: 1. Opens the mwdd32$ device (mwdd32.sys) 2. Sends IOCTL category 0xF0 function 0x42 to mwdd32$, with the following parameters : the FLAT pointer to the kernel's TKSSBase pointer. the FLAT pointer to a DevHelp32 structure the FLAT pointer to the 32 bits INIT routine the 16:16 pointer to the INIT request packet. 3. mwdd32$ updates the TKSSBase value, so that our driver can use the __StackToFlat() helper. 4. mwdd32$ fills the DevHelp32 structure with pointers to 32 bits DevHelp and utility functions, so that our driver can use them. 5. mwdd32$ calls back our 32 bits INIT routine at ring 0. 6. Upon return from our 32 bits routine, mwdd32$ stores the return code in the IOCTL data packet. 7. Upon return from the IOCTL call, the small 16 bits routine mentionned above retrieves the return code from the IOCTL data packet, and passes it back to the kernel. ═══ 7.2. 32 bits base (BASEDEV) device driver ═══ Location: ·/32bits/ext2-os2/skeleton/basedev Device driver initialization: Unlike regular device drivers, base device drivers initialize at ring 0. In this case, the 32 bits INIT BASE routine can be called directly. The first think the INIT base does is to call a routine which does the following: 1. Attaches to the mwdd32$ device (mwdd32.sys) 2. Calls mwdd32$'s IDC entry point, with the following parameters : the FLAT pointer to the kernel's TKSSBase pointer. the FLAT pointer to a DevHelp32 structure 3. mwdd32$ updates the TKSSBase value, so that our driver can use the __StackToFlat() helper. 4. mwdd32$ fills the DevHelp32 structure with pointers to 32 bits DevHelp and utility functions, so that our driver can use them. ═══ 7.3. 32 bits Installable File System (IFS) driver ═══ Location: ·/32bits/ext2-os2/skeleton/ifs IFS initialization: Installable File System drivers initialize at ring 3. Because at this time the FLAT code segment is unreachable (ring 0), the IFS cannot do a far call to its 32 bits initialization routine. To achieve 32 bits initialization, a small 16 bits routine called at INIT time does the following: 1. Opens the mwdd32$ device (mwdd32.sys) 2. Sends IOCTL category 0xF0 function 0x41 to mwdd32$, with the following parameters : the FLAT pointer to the kernel's TKSSBase pointer. the FLAT pointer to a DevHelp32 structure the FLAT pointer to the 32 bits IFS INIT routine the 16:16 pointer to the parameters passed to FS_INIT. 3. mwdd32$ updates the TKSSBase value, so that our driver can use the __StackToFlat() helper. 4. mwdd32$ fills the DevHelp32 structure with pointers to 32 bits DevHelp and utility functions, so that our driver can use them. 5. mwdd32$ converts the 16:16 pointer to FS_INIT parameters to 0:32. 6. mwdd32$ calls back our 32 bits IFS INIT routine at ring 0. 7. Upon return from our 32 bits routine, mwdd32$ stores the return code in the IOCTL data packet. 8. Upon return from the IOCTL call, the small 16 bits routine mentionned above retrieves the return code from the IOCTL data packet, and passes it back to the kernel. ═══ 7.4. 32 bits OS/2 Security Enabling Services (SES) driver ═══ Location: ·/32bits/ext2-os2/skeleton/ses OS/2 SES driver Initialization: An OS/2 Security device driver is actually a base device driver, so the first part of the initialization phase is similar to a BASEDEV initialization phase. In addition to the BASEDEV initialization phase, an OS/2 security driver must at least issue the following: 1. Call the kernel DevHlp32_Security helper to retrieve 32 bits kernel SecHlp entry points. 2. Call the kernel DevHlp32_Security helper to pass to the kernel the addresses of our security callbacks. 3. Attach to SES's sesdd32.sys and call its IDC entry point to retrieve 32 bits sesdd32.sys's SecHlp entry points. Once done, in our example, the only non NULL callback is OPEN_PRE. This callback will be called each time a file is opened by the kernel (DosOpen) before the actual open operation is done. Our sample checks if the file name matches CONFIG.* and returns ERROR_ACCESS_DENIED if it is the case. ═══ 8. History of changes ═══ This chapter describes the changes between each release of mwdd32. 1. From 1.10 to 1.20 2. From 1.20 to 1.30 3. From 1.30 to 1.40 4. From 1.40 to 1.50 5. From 1.50 to 1.60 6. From 1.60 to 1.70 ═══ 8.1. From 1.10 to 1.20 ═══  Corrected a stupid packaging error (some sources were missing).  Added the following utility functions : strtol  Added swapper entry points to fsh32.lib and to the sample IFS skeleton : FS_ALLOCATEPAGESPACE FS_DOPAGEIO FS_OPENPAGEFILE  Added a "-q" command line switch to mwdd32.sys (quiet initialization). ═══ 8.2. From 1.20 to 1.30 ═══  Added the following fsh32 functions : fsh32_addshare fsh32_removeshare fsh32_setvolume  Added the following utility functions : sec32_attach_ses  Added support for 32 bits DEVICE drivers, as well as a sample skeleton.  Added support for 32 bits SES (Security Enabling Services) drivers, as well as a sample skeleton. ═══ 8.3. From 1.30 to 1.40 ═══  Corrected a bug in DevHlp32_InternalError (the beginning of the message was truncated).  Corrected a bug in fsh32_devioctl (I think I was tired when I first wrote it !)  Added the following DevHlp32 functions : DevHlp32_setIRQ DevHlp32_UnSetIRQ DevHlp32_EOI  Added a sample 32 bits interrupt handler in the BASEDEV skeleton ═══ 8.4. From 1.40 to 1.50 ═══  Added the following DevHlp32 functions : DevHlp32_PageListToLin DevHlp32_AllocGDTSelector DevHlp32_FreeGDTSelector DevHlp32_AttachDD DevHlp32_GetDosVar ═══ 8.5. From 1.50 to 1.60 ═══  Holger Veit added the following DevHlp32 functions : DevHlp32_CloseEventSem DevHlp32_OpenEventSem DevHlp32_PostEventSem DevHlp32_ResetEventSem DevHlp32_VerifyAccess ═══ 8.6. From 1.60 to 1.70 ═══  Upgraded from ALP 4.00.000 to ALP 4.00.001. This corrected some code generation problems.  Corrected a bug in DevHlp32_ProcBlock (return code was garbage).  described in the file readme.doc in ./skeleton/watcom/watcom.zip. ═══ ═══  util/vsprintf.c ═══ ═══  util/atol.c  util/ctype.c  util/fnmatch.c  util/strpbrk.c  util/strtoul.c  util/strtol.c  util/strupr.c  util/strtok.c  include/os2/fnmatch.h  include/os2/ctype.h ═══ ═══  devhlp32/DevHlp32_CloseEventSem.asm  devhlp32/DevHlp32_OpenEventSem.asm  devhlp32/DevHlp32_PostEventSem.asm  devhlp32/DevHlp32_ResetEventSem.asm  devhlp32/DevHlp32_VerifyAccess.asm