[Compuware Corporation] [Compuware NuMega home page] [NuMega Lab] [teal] [DriverStudio] [Image][Image] · Home [Driver Products] Driver Technical Tips · DriverStudio A Better Way to Provide VxD to VxD Services · DriverBundle · Previews When a VxD wants to export services to other VxDs, the conventional approach is · Compatibility to create a VxD service table. The VxD service table contains the addresses of [Downloads] · the services to be exported, and there is a pointer to the table in the VxD's Device Data Block (DDB). Other VxDs call the exported services using macro Wizards VxDCall. This macro issues instruction INT 20h, which is trapped by the system. · Utilities The system's INT 20h handler examines the DWORD that immediately follows the · NT source INT instruction to determine which VxD service is being called. The exporter examples VxD is identified by a device ID constant, and the service within that VxD by · VxD source an ordinal value. The INT 20h locates the DDB of the exporter VxD, finds its examples service table, extracts the function address, and then patches over the INT 20h · WDM source in the caller's instruction stream with a CALL instruction that invokes the examples target VxD service. [Resources] · Technical papers While this mechanism is certainly tried and true, it has some disadvantages. · Useful links First, the declaration of the VxD service table requires use of a few ugly · Technical tips macros. Then the address of the table and the service count must be inserted [Support] · into the DDB. These details create opportunities to introduce bugs. Ensuring matching calling sequences and calling conventions (i.e. __stdcall vs. __cdecl) Support complicates it further. Another headache is obtaining a unique device ID to · Knowledge base designate the exporter VxD. VxD ID constants are allocated only by Microsoft, · Problem so if you arbitrarily assign one, then your VxD could conflict with some other submission VxD. · Product registration There is an alternative approach to exporting VxD services which addresses some · Release notes of these problems. You can use the system service Directed_Sys_Control to send [Shop NuMega] · a control message to the exporter VxD. Typically, the control message that you Buy it! send is the general purpose W32_DEVICEIOCONTROL. In other words, a VxD can · Price list export a set of services, each of which corresponds to a unique identifier · How to buy passed with the W32_DEVICEIOCONTROL message. · Sales offices In the VxD that exports the services, using this method is as simple as adding cases to a switch statement in the handler for W32_DEVICEIOCONTROL. However, [Y2K Compliance] the first step is to create a shared include file that defines the set of identifiers for the services. This is done with macro CTL_CODE: [More information] // my_ioctls.h #define IOCTL_MYDRIVER_SERVICE_1 \ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_NEITHER, FILE_ANY_ACCESS) #define IOCTL_MYDRIVER_SERVICE_2 \ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_NEITHER, FILE_ANY_ACCESS) #define IOCTL_MYDRIVER_SERVICE_3 \ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_NEITHER, FILE_ANY_ACCESS) The code above defines three constants that identify the exported services. So the handler for W32_DEVICEIOCONTROL in the exporter VxD looks like this (using VtoolsD): DWORD OnW32Deviceiocontrol(PIOCTLPARAMS p) { switch (p->dioc_IOCtlCode) { case DIOC_OPEN: // CreateFile case DIOC_CLOSEHANDLE: // handle closed return DEVIOCTL_NOERROR; case IOCTL_MYDRIVER_SERVICE_1: // implement service 1 break; case IOCTL_MYDRIVER_SERVICE_2: // implement service 2 break; case IOCTL_MYDRIVER_SERVICE_3: // implement service 3 break; default: return 1; // bad function } } In order to use Directed_Sys_Control from the calling VxD to send a message to the exporter VxD, you must first locate the DDB of the exporter VxD. This has to be done just once, not each time the calling VxD sends a message. To locate the DDB of the target device, use system service Get_DDB. Once you have a valid DDB pointer, use this function to call the exported service: BOOL SendDeviceIoControl( PDDB pDdb, // pointer to DDB of exporter VxD ULONG IoctlCode, // dioc_IOCtlCode PVOID InputBuffer, // dioc_InBuf ULONG SizeOfInputBuffer, // dioc_cbInBuf PVOID OutputBuffer, // dioc_OutBuf ULONG SizeOfOutputBuffer,// dioc_cbOutBuf PULONG pBytesReturned // dioc_bytesret ) { ALLREGS regs; // register struct passed to Directed_Sys_Ctrl IOCTLPARAMS io; // Ioctl param struct passed to target device if ( pDdb == NULL ) return FALSE; // set up the ioctl params io.dioc_IOCtlCode = IoctlCode; io.dioc_InBuf = InputBuffer; io.dioc_cbInBuf = SizeOfInputBuffer; io.dioc_OutBuf = OutputBuffer; io.dioc_cbOutBuf = SizeOfOutputBuffer; io.dioc_bytesret = pBytesReturned; // clear the regs structure memset(®s, 0, sizeof(regs)); // put a pointer to the ioctl param struct in the register struct regs.RESI = (DWORD)&io; // send the message to the target device Directed_Sys_Control(pDdb, W32_DEVICEIOCONTROL, ®s); return (regs.REAX == DEVIOCTL_NOERROR); } The parameters to the SendDeviceIoControl become the indicated members of the IOCTLPARAMS structure that the exporter VxD receives in its handler for control message W32_DEVICEIOCONTROL. You can customize a set of services using this general mechanism. Compared to the conventional VxD service table method, the Directed_Sys_Control method has some clear advantages. It avoids the use of complicated and error prone macros. There is a single fixed calling convention which can be safely adapted to an arbitrary set of services. You don't need to obtain a unique device ID constant from Microsoft. And if you will be porting the VxD to an NT or WDM driver in the future, the code will be much easier to port. One note of warning. Directed_Sys_Control does not validate the DDB pointer passed to it, so the exporter VxD and its caller should establish a protocol that provides the caller of some notification when the exporter unloads. Back to technical tip start page. DriverCentral · DriverStudio · Free downloads · Resources · Support and Services · Shop NuMega Compuware NuMega · Tel: +1 603 578-8400 · Updated: 9 August 1999 · Problems? Contact our webmaster.