ReactOS  0.4.13-dev-563-g0561610
info.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS TCP/IP protocol driver
4  * FILE: tcpip/info.c
5  * PURPOSE: TDI query and set information routines
6  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7  * REVISIONS:
8  * CSH 01/08-2000 Created
9  */
10 
11 #include "precomp.h"
12 
13 #include <debug.h>
14 
16 {
17  KIRQL OldIrql;
18  ULONG i, Instance = 0;
19  BOOLEAN ChoseIndex = FALSE;
20 
22 
23  while (!ChoseIndex)
24  {
25  ChoseIndex = TRUE;
26  for (i = 0; i < EntityCount; i++)
27  {
28  if (EntityList[i].tei_entity == EntityType &&
29  EntityList[i].tei_instance == Instance)
30  {
31  Instance++;
32  ChoseIndex = FALSE;
33  }
34  }
35  }
36 
37  EntityList[EntityCount].tei_entity = EntityType;
41  EntityCount++;
42 
44 }
45 
47 {
48  ULONG i;
49  KIRQL OldIrql;
50 
52 
53  for (i = 0; i < EntityCount; i++) {
54  if( EntityList[i].context == Context ) {
55  if( i != EntityCount - 1 ) {
56  memcpy( &EntityList[i],
58  sizeof(EntityList[i]) );
59  } else {
60  EntityCount--;
61  }
62  }
63  }
64 
66 }
67 
69 {
70  UINT i;
71  KIRQL OldIrql;
72  PVOID Context;
73 
75 
76  for (i = 0; i < EntityCount; i++)
77  {
78  if (EntityList[i].tei_entity == ID.tei_entity &&
79  EntityList[i].tei_instance == ID.tei_instance)
80  break;
81  }
82 
83  if (i == EntityCount)
84  {
86  DbgPrint("WARNING: Unable to get context for %d %d\n", ID.tei_entity, ID.tei_instance);
87  return NULL;
88  }
89 
91 
93 
94  return Context;
95 }
96 
97 TDI_STATUS InfoCopyOut( PCHAR DataOut, UINT SizeOut,
98  PNDIS_BUFFER ClientBuf, PUINT ClientBufSize ) {
99  UINT RememberedCBSize = *ClientBufSize;
100  *ClientBufSize = SizeOut;
101 
102  /* The driver returns success even when it couldn't fit every available
103  * byte. */
104  if( RememberedCBSize < SizeOut || !ClientBuf )
105  return TDI_SUCCESS;
106  else {
107  CopyBufferToBufferChain( ClientBuf, 0, (PCHAR)DataOut, SizeOut );
108  return TDI_SUCCESS;
109  }
110 }
111 
115 {
116  KIRQL OldIrql;
117  UINT i, Flags = 0;
118 
120 
121  for (i = 0; i < EntityCount; i++)
122  {
123  if (EntityList[i].tei_entity == ID.tei_entity &&
124  EntityList[i].tei_instance == ID.tei_instance)
125  break;
126  }
127 
128  if (i == EntityCount)
129  {
131  return TDI_INVALID_PARAMETER;
132  }
133 
134  Flags = EntityList[i].flags;
135 
137  sizeof(ULONG),
138  Buffer,
139  BufferSize);
140 
142 
143  return TDI_SUCCESS;
144 }
145 
148 {
150  KIRQL OldIrql;
151 
152  TI_DbgPrint(DEBUG_INFO,("About to copy %d TDIEntityIDs to user\n",
153  EntityCount));
154 
156 
157  Size = EntityCount * sizeof(TDIEntityID);
158  *BufferSize = Size;
159 
160  TI_DbgPrint(DEBUG_INFO,("BufSize: %d, NeededSize: %d\n", BufSize, Size));
161 
162  if (BufSize < Size || !Buffer)
163  {
165  /* The buffer is too small to contain requested data, but we return
166  * success anyway, as we did everything we wanted. */
167  return TDI_SUCCESS;
168  }
169 
170  /* Return entity list -- Copy only the TDIEntityID parts. */
171  for( Count = 0; Count < EntityCount; Count++ ) {
173  Count * sizeof(TDIEntityID),
175  sizeof(TDIEntityID));
176  }
177 
179 
180  return TDI_SUCCESS;
181 }
182 
185  TDIEntityID ID,
189 {
190  ULONG ATInfo[2];
192 
193  TI_DbgPrint(DEBUG_INFO, ("Called.\n"));
194 
195  if (!Interface)
196  return TDI_INVALID_PARAMETER;
197 
198  if (*BufferSize < sizeof(ATInfo))
200 
201  /* FIXME: I have no idea what the first field should contain... */
202  ATInfo[0] = 0;
203  ATInfo[1] = Interface->Index;
204 
205  Status = InfoCopyOut((PCHAR)ATInfo,
206  sizeof(ATInfo),
207  Buffer,
208  BufferSize);
209 
210  TI_DbgPrint(DEBUG_INFO, ("Returning %08x\n", Status));
211 
212  return Status;
213 }
214 
217  TDIObjectID *ID,
220  PVOID Context)
221 /*
222  * FUNCTION: Returns extended information
223  * ARGUMENTS:
224  * Request = Pointer to TDI request structure for the request
225  * ID = TDI object ID
226  * Buffer = Pointer to buffer with data to use
227  * BufferSize = Pointer to buffer with size of Buffer. On return
228  * this is filled with number of bytes returned
229  * Context = Pointer to context buffer
230  * RETURNS:
231  * Status of operation
232  */
233 {
234  PVOID EntityListContext;
235 
237  ("InfoEx Req: %x %x %x!%04x:%d\n",
238  ID->toi_class,
239  ID->toi_type,
240  ID->toi_id,
241  ID->toi_entity.tei_entity,
242  ID->toi_entity.tei_instance));
243 
244  switch (ID->toi_class)
245  {
246  case INFO_CLASS_GENERIC:
247  switch (ID->toi_id)
248  {
249  case ENTITY_LIST_ID:
250  if (ID->toi_type != INFO_TYPE_PROVIDER)
251  return TDI_INVALID_PARAMETER;
252 
254 
255  case ENTITY_TYPE_ID:
256  if (ID->toi_type != INFO_TYPE_PROVIDER)
257  return TDI_INVALID_PARAMETER;
258 
259  return InfoTdiQueryEntityType(ID->toi_entity, Buffer, BufferSize);
260 
261  default:
262  return TDI_INVALID_REQUEST;
263  }
264 
265  case INFO_CLASS_PROTOCOL:
266  if (ID->toi_type == INFO_TYPE_ADDRESS_OBJECT)
267  {
268  if ((EntityListContext = GetContext(ID->toi_entity)))
269  return GetAddressFileInfo(ID, EntityListContext, Buffer, BufferSize);
270  else
271  return TDI_INVALID_PARAMETER;
272  }
273 
274  switch (ID->toi_id)
275  {
276  case IF_MIB_STATS_ID:
277  if (ID->toi_type != INFO_TYPE_PROVIDER)
278  return TDI_INVALID_PARAMETER;
279 
280  if (ID->toi_entity.tei_entity == IF_ENTITY)
281  if ((EntityListContext = GetContext(ID->toi_entity)))
282  return InfoTdiQueryGetInterfaceMIB(ID->toi_entity, EntityListContext, Buffer, BufferSize);
283  else
284  return TDI_INVALID_PARAMETER;
285  else if (ID->toi_entity.tei_entity == CL_NL_ENTITY ||
286  ID->toi_entity.tei_entity == CO_NL_ENTITY)
287  if ((EntityListContext = GetContext(ID->toi_entity)))
288  return InfoTdiQueryGetIPSnmpInfo(ID->toi_entity, EntityListContext, Buffer, BufferSize);
289  else
290  return TDI_INVALID_PARAMETER;
291  else if (ID->toi_entity.tei_entity == AT_ENTITY)
292  if ((EntityListContext = GetContext(ID->toi_entity)))
293  return InfoTdiQueryGetATInfo(ID->toi_entity, EntityListContext, Buffer, BufferSize);
294  else
295  return TDI_INVALID_PARAMETER;
296  else
297  return TDI_INVALID_PARAMETER;
298 
300  if (ID->toi_type != INFO_TYPE_PROVIDER)
301  return TDI_INVALID_PARAMETER;
302 
303  if (ID->toi_entity.tei_entity == CL_NL_ENTITY ||
304  ID->toi_entity.tei_entity == CO_NL_ENTITY)
305  return InfoTdiQueryGetAddrTable(ID->toi_entity, Buffer, BufferSize);
306  else if (ID->toi_entity.tei_entity == CO_TL_ENTITY)
307  if ((EntityListContext = GetContext(ID->toi_entity)))
309  else
310  return TDI_INVALID_PARAMETER;
311  else if (ID->toi_entity.tei_entity == CL_TL_ENTITY)
312  if ((EntityListContext = GetContext(ID->toi_entity)))
314  else
315  return TDI_INVALID_PARAMETER;
316  else
317  return TDI_INVALID_PARAMETER;
318 
320  if (ID->toi_type != INFO_TYPE_PROVIDER)
321  return TDI_INVALID_PARAMETER;
322 
323  if (ID->toi_entity.tei_entity == AT_ENTITY)
324  if ((EntityListContext = GetContext(ID->toi_entity)))
325  return InfoTdiQueryGetArptableMIB(ID->toi_entity, EntityListContext,
326  Buffer, BufferSize);
327  else
328  return TDI_INVALID_PARAMETER;
329  else if (ID->toi_entity.tei_entity == CO_NL_ENTITY ||
330  ID->toi_entity.tei_entity == CL_NL_ENTITY)
331  if ((EntityListContext = GetContext(ID->toi_entity)))
332  return InfoTdiQueryGetRouteTable(EntityListContext, Buffer, BufferSize);
333  else
334  return TDI_INVALID_PARAMETER;
335  else if (ID->toi_entity.tei_entity == CO_TL_ENTITY)
336  if ((EntityListContext = GetContext(ID->toi_entity)))
338  else
339  return TDI_INVALID_PARAMETER;
340  else if (ID->toi_entity.tei_entity == CL_TL_ENTITY)
341  if ((EntityListContext = GetContext(ID->toi_entity)))
343  else
344  return TDI_INVALID_PARAMETER;
345  else
346  return TDI_INVALID_PARAMETER;
347 
348  case IP_SPECIFIC_MODULE_ENTRY_ID:
349  if (ID->toi_type != INFO_TYPE_PROVIDER)
350  return TDI_INVALID_PARAMETER;
351 
352  if (ID->toi_entity.tei_entity == CO_TL_ENTITY)
353  if ((EntityListContext = GetContext(ID->toi_entity)))
355  else
356  return TDI_INVALID_PARAMETER;
357  else if (ID->toi_entity.tei_entity == CL_TL_ENTITY)
358  if ((EntityListContext = GetContext(ID->toi_entity)))
360  else
361  return TDI_INVALID_PARAMETER;
362  else
363  return TDI_INVALID_PARAMETER;
364 
365 #if 0
366  case IP_INTFC_INFO_ID:
367  if (ID->toi_type != INFO_TYPE_PROVIDER)
368  return TDI_INVALID_PARAMETER;
369 
370  return InfoTdiQueryGetIFInfo(Context, Buffer, BufferSize);
371 #endif
372 
373  default:
374  return TDI_INVALID_REQUEST;
375  }
376 
377  default:
378  return TDI_INVALID_REQUEST;
379  }
380 }
381 
384  TDIObjectID *ID,
385  PVOID Buffer,
387 /*
388  * FUNCTION: Sets extended information
389  * ARGUMENTS:
390  * Request = Pointer to TDI request structure for the request
391  * ID = Pointer to TDI object ID
392  * Buffer = Pointer to buffer with data to use
393  * BufferSize = Size of Buffer
394  * RETURNS:
395  * Status of operation
396  */
397 {
398  PVOID EntityListContext;
399 
400  switch (ID->toi_class)
401  {
402  case INFO_CLASS_PROTOCOL:
403  {
404  switch (ID->toi_type)
405  {
407  {
408  if ((EntityListContext = GetContext(ID->toi_entity)))
409  return SetAddressFileInfo(ID, EntityListContext, Buffer, BufferSize);
410  else
411  return TDI_INVALID_PARAMETER;
412  }
414  {
415  PADDRESS_FILE AddressFile = GetContext(ID->toi_entity);
416  if (AddressFile == NULL)
417  return TDI_INVALID_PARAMETER;
418  return SetConnectionInfo(ID, AddressFile->Connection, Buffer, BufferSize);
419  }
420  case INFO_TYPE_PROVIDER:
421  {
422  switch (ID->toi_id)
423  {
425  if (ID->toi_type != INFO_TYPE_PROVIDER)
426  return TDI_INVALID_PARAMETER;
427 
428  if (ID->toi_entity.tei_entity == AT_ENTITY)
429  if ((EntityListContext = GetContext(ID->toi_entity)))
430  return InfoTdiSetArptableMIB(EntityListContext, Buffer,
431  BufferSize);
432  else
433  return TDI_INVALID_PARAMETER;
434  else if (ID->toi_entity.tei_entity == CL_NL_ENTITY
435  || ID->toi_entity.tei_entity == CO_NL_ENTITY)
436  if ((EntityListContext = GetContext(ID->toi_entity)))
437  return InfoTdiSetRoute(EntityListContext, Buffer, BufferSize);
438  else
439  return TDI_INVALID_PARAMETER;
440  else
441  return TDI_INVALID_PARAMETER;
442 
443  default:
444  return TDI_INVALID_REQUEST;
445  }
446  }
447  default:
448  DbgPrint("TCPIP: IOCTL_TCP_SET_INFORMATION_EX - Unrecognized information type for INFO_CLASS_PROTOCOL: %#x.\n", ID->toi_type);
449  return TDI_INVALID_PARAMETER;
450  }
451  break;
452  }
453  default:
454  DbgPrint("TCPIP: IOCTL_TCP_SET_INFORMATION_EX - Unrecognized information class %#x.\n", ID->toi_class);
455  return TDI_INVALID_REQUEST;
456  }
457 }
UINT CopyBufferToBufferChain(PNDIS_BUFFER DstBuffer, UINT DstOffset, PUCHAR SrcData, UINT Length)
Definition: buffer.c:54
signed char * PCHAR
Definition: retypes.h:7
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
#define AT_ENTITY
Definition: tdiinfo.h:41
ULONG EntityCount
Definition: main.c:24
#define TRUE
Definition: types.h:120
VOID RemoveEntityByContext(PVOID Context)
Definition: info.c:46
#define TDI_SUCCESS
Definition: tdistat.h:30
KSPIN_LOCK EntityListLock
Definition: main.c:22
#define DbgPrint
Definition: loader.c:25
Definition: http.c:6587
TDI_STATUS InfoTdiQueryGetRouteTable(PIP_INTERFACE IF, PNDIS_BUFFER Buffer, PUINT BufferSize)
Definition: ninfo.c:17
struct _TDIEntityID TDIEntityID
MDL * PNDIS_BUFFER
Definition: ndis.h:343
TDI_STATUS InfoCopyOut(PCHAR DataOut, UINT SizeOut, PNDIS_BUFFER ClientBuf, PUINT ClientBufSize)
Definition: info.c:97
TDIEntityInfo * EntityList
Definition: main.c:23
TDI_STATUS InfoTdiQueryGetArptableMIB(TDIEntityID ID, PIP_INTERFACE Interface, PNDIS_BUFFER Buffer, PUINT BufferSize)
Definition: iinfo.c:105
TDI_STATUS GetAddressFileInfo(TDIObjectID *ID, PADDRESS_FILE AddrFile, PVOID Buffer, PUINT BufferSize)
Definition: ainfo.c:67
#define ENTITY_TYPE_ID
Definition: tdiinfo.h:39
TDI_STATUS InfoTdiQueryListEntities(PNDIS_BUFFER Buffer, PUINT BufferSize)
Definition: info.c:146
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
LONG TDI_STATUS
Definition: tdi.h:36
#define INFO_TYPE_CONNECTION
Definition: tdiinfo.h:71
UINT tei_entity
Definition: tcpip.h:146
VOID TcpipReleaseSpinLock(PKSPIN_LOCK SpinLock, KIRQL Irql)
Definition: lock.c:26
VOID TcpipAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL Irql)
Definition: lock.c:18
#define IP_MIB_ARPTABLE_ENTRY_ID
Definition: tcpioctl.h:51
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
VOID AddEntity(ULONG EntityType, PVOID Context, ULONG Flags)
Definition: info.c:15
_In_ NDIS_HANDLE _In_ PNDIS_REQUEST Request
Definition: ndis.h:5173
UCHAR KIRQL
Definition: env_spec_w32.h:591
PVOID GetContext(TDIEntityID ID)
Definition: info.c:68
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
TDI_STATUS InfoTdiQueryEntityType(TDIEntityID ID, PNDIS_BUFFER Buffer, PUINT BufferSize)
Definition: info.c:112
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define CO_TL_ENTITY
Definition: tdiinfo.h:45
Definition: bufpool.h:45
TDI_STATUS InfoTdiQueryGetAddrTable(TDIEntityID ID, PNDIS_BUFFER Buffer, PUINT BufferSize)
Definition: ninfo.c:98
#define BufSize
Definition: FsRtlTunnel.c:28
UINT tei_instance
Definition: tcpip.h:147
IN PVOID IN PVOID IN USHORT IN USHORT IN PINTERFACE Interface
Definition: pci.h:359
TDI_STATUS InfoTdiQueryGetATInfo(TDIEntityID ID, PIP_INTERFACE Interface, PNDIS_BUFFER Buffer, PUINT BufferSize)
Definition: info.c:184
#define INFO_CLASS_GENERIC
Definition: tdiinfo.h:64
TDI_STATUS InfoTdiQueryGetInterfaceMIB(TDIEntityID ID, PIP_INTERFACE Interface, PNDIS_BUFFER Buffer, PUINT BufferSize)
Definition: iinfo.c:18
PVOID context
Definition: tcpip.h:148
#define BufferSize
Definition: classpnp.h:419
#define IF_ENTITY
Definition: tdiinfo.h:47
#define CO_NL_ENTITY
Definition: tdiinfo.h:44
#define CL_NL_ENTITY
Definition: tdiinfo.h:42
#define TDI_INVALID_PARAMETER
Definition: tdistat.h:52
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define INFO_TYPE_ADDRESS_OBJECT
Definition: tdiinfo.h:70
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ID
Definition: ruserpass.c:36
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
TDI_STATUS InfoTdiQueryGetIPSnmpInfo(TDIEntityID ID, PIP_INTERFACE IF, PNDIS_BUFFER Buffer, PUINT BufferSize)
Definition: ninfo.c:155
#define IF_MIB_STATS_ID
Definition: tcpioctl.h:49
TDI_STATUS InfoTdiQueryInformationEx(PTDI_REQUEST Request, TDIObjectID *ID, PNDIS_BUFFER Buffer, PUINT BufferSize, PVOID Context)
Definition: info.c:215
Status
Definition: gdiplustypes.h:24
TDI_STATUS SetConnectionInfo(TDIObjectID *ID, PCONNECTION_ENDPOINT Connection, PVOID Buffer, UINT BufferSize)
Definition: cinfo.c:11
#define CL_TL_ENTITY
Definition: tdiinfo.h:43
TDI_STATUS InfoTdiSetInformationEx(PTDI_REQUEST Request, TDIObjectID *ID, PVOID Buffer, UINT BufferSize)
Definition: info.c:383
UINT flags
Definition: tcpip.h:149
#define ENTITY_LIST_ID
Definition: tdiinfo.h:38
unsigned int UINT
Definition: ndis.h:50
TDI_STATUS InfoTdiSetRoute(PIP_INTERFACE IF, PVOID Buffer, UINT BufferSize)
Definition: ninfo.c:310
IN PVOID Instance
Definition: pci.h:359
TDI_STATUS SetAddressFileInfo(TDIObjectID *ID, PADDRESS_FILE AddrFile, PVOID Buffer, UINT BufferSize)
Definition: ainfo.c:11
#define INFO_TYPE_PROVIDER
Definition: tdiinfo.h:69
struct tagContext Context
Definition: acpixf.h:1012
unsigned int ULONG
Definition: retypes.h:1
struct _CONNECTION_ENDPOINT * Connection
Definition: titypes.h:151
#define IP_INTFC_INFO_ID
Definition: tcpioctl.h:53
#define IP_MIB_ADDRTABLE_ENTRY_ID
Definition: afd.h:36
TDI_STATUS InfoTdiSetArptableMIB(PIP_INTERFACE IF, PVOID Buffer, UINT BufferSize)
Definition: iinfo.c:133
#define DEBUG_INFO
Definition: debug.h:33
TDI_STATUS InfoTdiQueryGetConnectionTcpTable(PADDRESS_FILE AddrFile, PNDIS_BUFFER Buffer, PUINT BufferSize, TDI_TCPUDP_CLASS_INFO Class)
Definition: ninfo.c:182
#define TDI_INVALID_REQUEST
Definition: tdistat.h:63
unsigned int * PUINT
Definition: ndis.h:50
TDI_STATUS InfoTdiQueryGetConnectionUdpTable(PADDRESS_FILE AddrFile, PNDIS_BUFFER Buffer, PUINT BufferSize, TDI_TCPUDP_CLASS_INFO Class)
Definition: ninfo.c:267
#define INFO_CLASS_PROTOCOL
Definition: tdiinfo.h:65