extensions/sdktools/vcallbuilder.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jun 20 07:08:53 2007 +0000 (2007-06-20)
changeset 986 c5e856eba68d
parent 975 f161d9fadee2
child 987 242d2382cc41
permissions -rw-r--r--
fixed a bug where thisinfo could be constructed with garbage data for decflags
dvander@950
     1
#include "vcallbuilder.h"
dvander@950
     2
#include "extension.h"
dvander@950
     3
dvander@974
     4
ValveCall::ValveCall()
dvander@974
     5
{
dvander@974
     6
	call = NULL;
dvander@974
     7
	vparams = NULL;
dvander@974
     8
	retinfo = NULL;
dvander@974
     9
	thisinfo = NULL;
dvander@974
    10
	retbuf = NULL;
dvander@974
    11
}
dvander@974
    12
dvander@950
    13
ValveCall::~ValveCall()
dvander@950
    14
{
dvander@950
    15
	while (!stk.empty())
dvander@950
    16
	{
dvander@950
    17
		unsigned char *ptr = stk.front();
dvander@950
    18
		delete [] ptr;
dvander@950
    19
		stk.pop();
dvander@950
    20
	}
dvander@975
    21
	if (call)
dvander@975
    22
	{
dvander@975
    23
		call->Destroy();
dvander@975
    24
	}
dvander@950
    25
	delete [] retbuf;
dvander@950
    26
	delete [] vparams;
dvander@950
    27
}
dvander@950
    28
dvander@950
    29
unsigned char *ValveCall::stk_get()
dvander@950
    30
{
dvander@950
    31
	unsigned char *ptr;
dvander@950
    32
	if (stk.empty())
dvander@950
    33
	{
dvander@950
    34
		ptr = new unsigned char[stackSize];
dvander@950
    35
	} else {
dvander@950
    36
		ptr = stk.front();
dvander@950
    37
		stk.pop();
dvander@950
    38
	}
dvander@950
    39
	return ptr;
dvander@950
    40
}
dvander@950
    41
dvander@950
    42
void ValveCall::stk_put(unsigned char *ptr)
dvander@950
    43
{
dvander@950
    44
	stk.push(ptr);
dvander@950
    45
}
dvander@950
    46
dvander@953
    47
ValveCall *CreateValveCall(void *addr,
dvander@953
    48
						   ValveCallType vcalltype,
dvander@953
    49
						   const ValvePassInfo *retInfo,
dvander@953
    50
						   const ValvePassInfo *params,
dvander@953
    51
						   unsigned int numParams)
dvander@953
    52
{
dvander@953
    53
	if (numParams > 32)
dvander@953
    54
	{
dvander@953
    55
		return NULL;
dvander@953
    56
	}
dvander@953
    57
dvander@953
    58
	ValveCall *vc = new ValveCall;
dvander@953
    59
dvander@953
    60
	size_t size = 0;
dvander@953
    61
	vc->stackSize = 0;
dvander@953
    62
dvander@953
    63
	/* Get return information - encode only*/
dvander@953
    64
	PassInfo retBuf;
dvander@953
    65
	size_t retBufSize = 0;
dvander@953
    66
	if (retInfo)
dvander@953
    67
	{
dvander@953
    68
		if ((size = ValveParamToBinParam(retInfo->vtype, retInfo->type, retInfo->flags, &retBuf)) == 0)
dvander@953
    69
		{
dvander@953
    70
			delete vc;
dvander@953
    71
			return NULL;
dvander@953
    72
		}
dvander@953
    73
		retBufSize = size;
dvander@953
    74
	}
dvander@953
    75
dvander@953
    76
	/* Get thisinfo if needed */
dvander@953
    77
	ValvePassInfo thisbuf;
dvander@953
    78
	ValvePassInfo *thisinfo = NULL;
dvander@953
    79
	CallConvention cv = CallConv_Cdecl;
dvander@953
    80
	if (vcalltype != ValveCall_Static)
dvander@953
    81
	{
dvander@953
    82
		thisinfo = &thisbuf;
dvander@953
    83
		thisinfo->type = PassType_Basic;
dvander@953
    84
		if (vcalltype == ValveCall_Entity)
dvander@953
    85
		{
dvander@953
    86
			thisinfo->vtype = Valve_CBaseEntity;
dvander@953
    87
			thisinfo->decflags |= VDECODE_FLAG_ALLOWWORLD;
dvander@953
    88
		} else if (vcalltype == ValveCall_Player) {
dvander@953
    89
			thisinfo->vtype = Valve_CBasePlayer;
dvander@953
    90
			thisinfo->decflags = 0;
dvander@953
    91
		}
dvander@953
    92
		thisinfo->encflags = 0;
dvander@953
    93
		thisinfo->flags = PASSFLAG_BYVAL;
dvander@953
    94
		thisinfo->offset = 0;
dvander@953
    95
		vc->stackSize += sizeof(void *);
dvander@953
    96
		cv = CallConv_ThisCall;
dvander@953
    97
	}
dvander@953
    98
dvander@953
    99
	/* Get parameter info */
dvander@953
   100
	PassInfo paramBuf[32];
dvander@953
   101
	for (unsigned int i=0; i<numParams; i++)
dvander@953
   102
	{
dvander@953
   103
		if ((size = ValveParamToBinParam(params[i].vtype, params[i].type, params[i].flags, &paramBuf[i])) == 0)
dvander@953
   104
		{
dvander@953
   105
			delete vc;
dvander@953
   106
			return NULL;
dvander@953
   107
		}
dvander@953
   108
		vc->stackSize += size;
dvander@953
   109
	}
dvander@953
   110
dvander@953
   111
	/* Now we can try creating the call */
dvander@953
   112
	if ((vc->call = g_pBinTools->CreateCall(addr,
dvander@953
   113
		cv,
dvander@953
   114
		(retInfo ? &retBuf : NULL),
dvander@953
   115
		paramBuf,
dvander@953
   116
		numParams))
dvander@953
   117
		== NULL)
dvander@953
   118
	{
dvander@953
   119
		if (!vc->call)
dvander@953
   120
		{
dvander@953
   121
			delete vc;
dvander@953
   122
			return NULL;
dvander@953
   123
		}
dvander@953
   124
	}
dvander@953
   125
dvander@953
   126
	/* Allocate extra space for thisptr AND ret buffer, even if we don't use it */
dvander@953
   127
	vc->vparams = new ValvePassInfo[numParams + 2];
dvander@953
   128
dvander@953
   129
	/* We've got the call and everything is encoded.
dvander@953
   130
	 * It's time to save the valve specific information and helper variables.
dvander@953
   131
	 */
dvander@953
   132
	if (retInfo)
dvander@953
   133
	{
dvander@953
   134
		/* Allocate and copy */
dvander@953
   135
		vc->retinfo = &(vc->vparams[numParams]);
dvander@953
   136
		*vc->retinfo = *retInfo;
dvander@953
   137
		vc->retinfo->offset = 0;
dvander@953
   138
		/* Allocate stack space */
dvander@953
   139
		vc->retbuf = new unsigned char[retBufSize];
dvander@953
   140
	} else {
dvander@953
   141
		vc->retinfo = NULL;
dvander@953
   142
		vc->retbuf = NULL;
dvander@953
   143
	}
dvander@953
   144
dvander@953
   145
	if (thisinfo)
dvander@953
   146
	{
dvander@953
   147
		/* Allocate and copy */
dvander@953
   148
		vc->thisinfo = &(vc->vparams[numParams + 1]);
dvander@953
   149
		*vc->thisinfo = *thisinfo;
dvander@953
   150
		vc->thisinfo->offset = 0;
dvander@953
   151
	} else {
dvander@953
   152
		vc->thisinfo = NULL;
dvander@953
   153
	}
dvander@953
   154
dvander@953
   155
	/* Now, save info about each parameter. */
dvander@953
   156
	for (unsigned int i=0; i<numParams; i++)
dvander@953
   157
	{
dvander@953
   158
		/* Copy */
dvander@953
   159
		vc->vparams[i] = params[i];
dvander@953
   160
		vc->vparams[i].offset = vc->call->GetParamInfo(i)->offset;
dvander@953
   161
	}
dvander@953
   162
dvander@953
   163
	return vc;
dvander@953
   164
}
dvander@953
   165
dvander@950
   166
ValveCall *CreateValveVCall(unsigned int vtableIdx,
dvander@950
   167
							ValveCallType vcalltype,
dvander@950
   168
							const ValvePassInfo *retInfo,
dvander@950
   169
							const ValvePassInfo *params,
dvander@950
   170
							unsigned int numParams)
dvander@950
   171
{
dvander@950
   172
	if (numParams > 32)
dvander@950
   173
	{
dvander@950
   174
		return NULL;
dvander@950
   175
	}
dvander@950
   176
dvander@950
   177
	ValveCall *vc = new ValveCall;
dvander@950
   178
dvander@950
   179
	size_t size = 0;
dvander@950
   180
	vc->stackSize = 0;
dvander@950
   181
dvander@950
   182
	/* Get return information - encode only*/
dvander@950
   183
	PassInfo retBuf;
dvander@950
   184
	size_t retBufSize = 0;
dvander@950
   185
	if (retInfo)
dvander@950
   186
	{
dvander@950
   187
		if ((size = ValveParamToBinParam(retInfo->vtype, retInfo->type, retInfo->flags, &retBuf)) == 0)
dvander@950
   188
		{
dvander@950
   189
			delete vc;
dvander@950
   190
			return NULL;
dvander@950
   191
		}
dvander@950
   192
		retBufSize = size;
dvander@950
   193
	}
dvander@950
   194
dvander@950
   195
	/* Get parameter info */
dvander@950
   196
	PassInfo paramBuf[32];
dvander@950
   197
	for (unsigned int i=0; i<numParams; i++)
dvander@950
   198
	{
dvander@950
   199
		if ((size = ValveParamToBinParam(params[i].vtype, params[i].type, params[i].flags, &paramBuf[i])) == 0)
dvander@950
   200
		{
dvander@950
   201
			delete vc;
dvander@950
   202
			return NULL;
dvander@950
   203
		}
dvander@950
   204
		vc->stackSize += size;
dvander@950
   205
	}
dvander@950
   206
dvander@950
   207
	/* Now we can try creating the call */
dvander@950
   208
	if ((vc->call = g_pBinTools->CreateVCall(vtableIdx, 
dvander@950
   209
		0, 
dvander@950
   210
		0, 
dvander@950
   211
		(retInfo ? &retBuf : NULL),
dvander@950
   212
		paramBuf,
dvander@950
   213
		numParams))
dvander@950
   214
		== NULL)
dvander@950
   215
	{
dvander@950
   216
		if (!vc->call)
dvander@950
   217
		{
dvander@950
   218
			delete vc;
dvander@950
   219
			return NULL;
dvander@950
   220
		}
dvander@950
   221
	}
dvander@950
   222
dvander@950
   223
	/* Allocate extra space for thisptr AND ret buffer, even if we don't use it */
dvander@950
   224
	vc->vparams = new ValvePassInfo[numParams + 2];
dvander@950
   225
dvander@950
   226
	/* We've got the call and everything is encoded.
dvander@950
   227
	 * It's time to save the valve specific information and helper variables.
dvander@950
   228
	 */
dvander@950
   229
	if (retInfo)
dvander@950
   230
	{
dvander@950
   231
		/* Allocate and copy */
dvander@950
   232
		vc->retinfo = &(vc->vparams[numParams]);
dvander@950
   233
		*vc->retinfo = *retInfo;
dvander@950
   234
		vc->retinfo->offset = 0;
dvander@950
   235
		/* Allocate stack space */
dvander@950
   236
		vc->retbuf = new unsigned char[retBufSize];
dvander@950
   237
	} else {
dvander@950
   238
		vc->retinfo = NULL;
dvander@950
   239
		vc->retbuf = NULL;
dvander@950
   240
	}
dvander@950
   241
dvander@950
   242
	/* Save the this info for the dynamic decoder */
dvander@950
   243
	vc->thisinfo = &(vc->vparams[numParams + 1]);
dvander@950
   244
	vc->thisinfo->type = PassType_Basic;
dvander@950
   245
	if (vcalltype == ValveCall_Entity)
dvander@950
   246
	{
dvander@950
   247
		vc->thisinfo->vtype = Valve_CBaseEntity;
dvander@986
   248
		vc->thisinfo->decflags = VDECODE_FLAG_ALLOWWORLD;
dvander@950
   249
	} else if (vcalltype == ValveCall_Player) {
dvander@950
   250
		vc->thisinfo->vtype = Valve_CBasePlayer;
dvander@950
   251
		vc->thisinfo->decflags = 0;
dvander@950
   252
	}
dvander@950
   253
	vc->thisinfo->encflags = 0;
dvander@950
   254
	vc->thisinfo->flags = PASSFLAG_BYVAL;
dvander@950
   255
	vc->thisinfo->offset = 0;
dvander@950
   256
	vc->stackSize += sizeof(void *);
dvander@950
   257
dvander@950
   258
	/* Now, save info about each parameter. */
dvander@950
   259
	for (unsigned int i=0; i<numParams; i++)
dvander@950
   260
	{
dvander@950
   261
		/* Copy */
dvander@950
   262
		vc->vparams[i] = params[i];
dvander@950
   263
		vc->vparams[i].offset = vc->call->GetParamInfo(i)->offset;
dvander@950
   264
	}
dvander@950
   265
dvander@950
   266
	return vc;
dvander@950
   267
}