int PacketHandler::chat_message(User *user) { // Wait for length-short. HEHE if(user->buffer.size() < 2) return PACKET_NEED_MORE_DATA; int curpos = 0; unsigned int i; uint8 tmpLenArray[2] = {0}; for(i = 0; i < 2; i++) tmpLenArray[i] = user->buffer[curpos+i]; short len = getSint16(&tmpLenArray[0]); curpos += 2; // Wait for whole message if(user->buffer.size() < (unsigned int)curpos+len) return PACKET_NEED_MORE_DATA; //Read message std::string msg; for(i = 0; i < (unsigned int)len; i++) msg += user->buffer[curpos+i]; curpos += len; // Remove from buffer user->buffer.erase(user->buffer.begin(), user->buffer.begin()+curpos); Chat::get().handleMsg( user, msg ); return curpos; }
int Drawboard::authenticate(Client* client) { uint32_t curpos = 1; uint32_t len=getUint16((uint8_t *)(&client->buffer[0]+curpos)); curpos += 2; #ifdef DEBUG std::cout << " Len: " << len << std::endl; #endif if(client->buffer.size()-curpos < len) { return NEED_MORE_DATA; } std::string hash(' ',32); int32_t UID=getSint16((uint8_t *)(&client->buffer[0]+curpos)); curpos += 2; uint8_t chanID = client->buffer[curpos]; curpos++; uint64_t timestamp = getUint64((uint8_t *)(&client->buffer[0]+curpos)); curpos += 8; uint8_t adminbit = client->buffer[curpos]; curpos++; memcpy((void *)hash.data(), (uint8_t *)(&client->buffer[0]+curpos),32); curpos += 32; uint32_t nicklen=client->buffer[curpos]; curpos++; std::string nick; for(uint32_t i = 0; i < nicklen; i++) { nick+=(char)client->buffer[curpos]; curpos ++; } //Clear the data from the buffer client->eraseFromBuffer(curpos); //ToDo: implement configuration reader etc if(0)//config.check_auth) { std::string user_time; myItoa(timestamp,user_time,10); //Check the auth data std::string combination=user_time+"|SECRET_STRING|"+(char)('0'+adminbit)+"|"+nick; std::string hash2; MD5_CTX mdContext; MD5Init (&mdContext); MD5Update (&mdContext, (unsigned char *)(combination.c_str()), combination.size()); MD5Final (&mdContext); for (int iii = 0; iii < 16; iii++) hash2+=toHex((unsigned int)mdContext.digest[iii]); if(hash2 != hash) { return DATA_ERROR; } } client->nick = nick; client->admin = (adminbit==0)?false:true; return DATA_OK; }
int PacketHandler::disconnect(User *user) { if(user->buffer.size() < 2) return PACKET_NEED_MORE_DATA; int curpos = 0; unsigned int i; uint8 shortArray[2]; for(i = 0; i < 2; i++) shortArray[i] = user->buffer[i]; int len = getSint16(&shortArray[0]); curpos += 2; // Wait for whole message if(user->buffer.size() < (unsigned int)curpos+len) return PACKET_NEED_MORE_DATA; //Read message std::string msg; for(i = 0; i < (unsigned int)len; i++) msg += user->buffer[curpos+i]; std::cout << "Disconnect: " << msg << std::endl; curpos += len; user->buffer.erase(user->buffer.begin(), user->buffer.begin()+curpos); bufferevent_free(user->buf_ev); #ifdef WIN32 closesocket(user->fd); #else close(user->fd); #endif remUser(user->fd); return curpos; }
void PacketHandler::pickup_spawn(uint8 *data, User *user) { uint32 curpos = 4; spawnedItem item; item.EID = generateEID(); item.health = 0; item.item = getSint16(&data[curpos]); curpos += 2; item.count = data[curpos]; curpos++; item.pos.x() = getSint32(&data[curpos]); curpos += 4; item.pos.y() = getSint32(&data[curpos]); curpos += 4; item.pos.z() = getSint32(&data[curpos]); curpos += 4; item.spawnedBy = user->UID; Map::get().sendPickupSpawn(item); }
int PacketHandler::handshake(User *user) { if(user->buffer.size() < 3) return PACKET_NEED_MORE_DATA; int curpos = 0; int i; //Player name length uint8 tmpShortArray[2] = {0}; for(i = 0; i < 2; i++) tmpShortArray[i] = user->buffer[curpos+i]; int len = getSint16(&tmpShortArray[0]); curpos += 2; //Check for data if(user->buffer.size() < (unsigned int)curpos+len) return PACKET_NEED_MORE_DATA; //Read player name std::string player; for(int pos = 0; pos < len; pos++) { player += user->buffer[curpos+pos]; } curpos += len; //Remove package from buffer user->buffer.erase(user->buffer.begin(), user->buffer.begin()+curpos); std::cout << "Handshake player: " << player << std::endl; //Send handshake package char data2[4] = {0x02, 0x00, 0x01, '-'}; bufferevent_write(user->buf_ev, (char *)&data2[0], 4); return curpos; }
void Map::idToPos(uint32 id, int *x, int *z) { uint8 *id_pointer = reinterpret_cast<uint8 *>(&id); *x = getSint16(&id_pointer[0]); *z = getSint16(&id_pointer[2]); }
NBT_Value::NBT_Value(eTAG_Type type, uint8 **buf, int &remaining) : m_type(type) { switch(m_type) { case TAG_BYTE: remaining--; if(remaining >= 0) { m_value.byteVal = **buf; (*buf)++; } break; case TAG_SHORT: remaining-=2; if(remaining >= 0) { m_value.shortVal = getSint16(*buf); *buf += 2; } break; case TAG_INT: remaining-=4; if(remaining >= 0) { m_value.intVal = getSint32(*buf); *buf += 4; } break; case TAG_LONG: remaining -= 8; if(remaining >= 0) { m_value.longVal = getSint64(*buf); *buf += 8; } break; case TAG_FLOAT: remaining -= 4; if(remaining >= 0) { m_value.floatVal = getFloat(*buf); *buf += 4; } break; case TAG_DOUBLE: remaining -= 8; if(remaining >= 0) { m_value.doubleVal = getDouble(*buf); *buf += 8; } break; case TAG_BYTE_ARRAY: remaining -= 4; if(remaining >= 0) { sint32 bufLen = getSint32(*buf); remaining -= bufLen; *buf += 4; if(remaining >= 0) { m_value.byteArrayVal = new std::vector<uint8>(); m_value.byteArrayVal->assign(*buf, (*buf)+bufLen); *buf += bufLen; } } break; case TAG_STRING: remaining -= 2; if(remaining >= 0) { sint16 stringLen = getSint16(*buf); remaining -= stringLen; *buf += 2; if(remaining >= 0) { m_value.stringVal = new std::string((char*)*buf, stringLen); *buf += stringLen; } } break; case TAG_LIST: remaining -= 5; if(remaining >= 0) { sint8 type = **buf; (*buf)++; m_value.listVal.type = (eTAG_Type)type; sint32 count = getSint32(*buf); *buf += 4; m_value.listVal.data = new std::vector<NBT_Value*>(); if(count) m_value.listVal.data->resize(count); for(int i=0;i<count;i++) { (*m_value.listVal.data)[i] = new NBT_Value((eTAG_Type)type, buf, remaining); } } break; case TAG_COMPOUND: m_value.compoundVal = new std::map<std::string, NBT_Value*>(); while(remaining > 0) { remaining--; sint8 type = **buf; (*buf)++; if(type == TAG_END) break; remaining -= 2; if(remaining <= 0) break; sint16 stringLen = getSint16(*buf); *buf += 2; remaining -= stringLen; if(remaining <= 0) break; std::string key((char*)*buf, stringLen); *buf += stringLen; (*m_value.compoundVal)[key] = new NBT_Value((eTAG_Type)type, buf, remaining); } break; case TAG_END: break; } }
int TAG_Short(uint8* input, int *output) { *output=getSint16(input); return 2; }
int PacketHandler::complex_entities(User *user) { if(user->buffer.size() < 12) return PACKET_NEED_MORE_DATA; int curpos = 0; unsigned int i; uint8 intArray[4]; uint8 shortArray[2]; std::copy(user->buffer.begin()+curpos, user->buffer.begin()+curpos+4, intArray); int x = getSint32(&intArray[0]); curpos += 4; std::copy(user->buffer.begin()+curpos, user->buffer.begin()+curpos+2, shortArray); int y = getSint16(&shortArray[0]); curpos += 2; std::copy(user->buffer.begin()+curpos, user->buffer.begin()+curpos+4, intArray); int z = getSint32(&intArray[0]); curpos += 4; std::copy(user->buffer.begin()+curpos, user->buffer.begin()+curpos+2, shortArray); int len = getSint16(&shortArray[0]); curpos += 2; // Wait for whole message if(user->buffer.size() < (unsigned int)curpos+len) return PACKET_NEED_MORE_DATA; //ToDo: check len uint8 *buffer = new uint8[len]; for(i = 0; i < (uint32)len; i++) { buffer[i] = user->buffer[curpos+i]; } curpos += len; user->buffer.erase(user->buffer.begin(), user->buffer.begin()+curpos); uint8 block, meta; Map::get().getBlock(x, y, z, &block, &meta); //We only handle chest for now if(block != BLOCK_CHEST) { delete[] buffer; return curpos; } //Calculate uncompressed size and allocate memory uLongf uncompressedSize = ALLOCATE_NBTFILE; //buffer[len-3] + (buffer[len-2]<<8) + (buffer[len-1]<<16) + (buffer[len]<<24); uint8 *uncompressedBuffer = new uint8[uncompressedSize]; //Initialize zstream to handle gzip format z_stream zstream; zstream.zalloc = (alloc_func)0; zstream.zfree = (free_func)0; zstream.opaque = (voidpf)0; zstream.next_in = buffer; zstream.next_out = uncompressedBuffer; zstream.avail_in = len; zstream.avail_out = uncompressedSize; zstream.total_in = 0; zstream.total_out = 0; zstream.data_type = Z_BINARY; inflateInit2(&zstream, 1+MAX_WBITS); //Uncompress if(/*int state=*/inflate(&zstream, Z_FULL_FLUSH)!=Z_OK) { inflateEnd(&zstream); } //Get size uncompressedSize = zstream.total_out; //Push data to NBT struct NBT_struct newObject; TAG_Compound(uncompressedBuffer, &newObject, true); //These are not needed anymore delete[] buffer; delete[] uncompressedBuffer; //Get chunk position int block_x = blockToChunk(x); int block_z = blockToChunk(z); uint32 chunkID; NBT_struct *theEntity = 0; //Load map if(Map::get().loadMap(block_x, block_z)) { Map::get().posToId(block_x, block_z, &chunkID); NBT_struct mapData = Map::get().maps[chunkID]; //Try to find entitylist from the chunk NBT_list *entitylist = get_NBT_list(&mapData, "TileEntities"); //If list exists if(entitylist) { //Verify list type if(entitylist->tagId != TAG_COMPOUND) { //If wrong type, recreate freeNBT_list(entitylist); for(i = 0; i < mapData.lists.size(); i++) { if(mapData.lists[i].name == "TileEntities") { //Destroy old list freeNBT_list(&mapData.lists[i]); mapData.lists.erase(mapData.lists.begin()+i); break; } } //New list NBT_list newlisting; newlisting.name = "TileEntities"; newlisting.tagId = TAG_COMPOUND; newlisting.length = 0; mapData.lists.push_back(newlisting); entitylist = get_NBT_list(&mapData, "TileEntities"); } NBT_struct **entities = (NBT_struct **)entitylist->items; bool entityExists = false; int existingID = -1; //Search for mathing entity in the list for(int i = 0; i < entitylist->length; i++) { NBT_struct *entity = entities[i]; std::string id; //Get ID if(get_NBT_value(entity, "id", &id)) { int entity_x, entity_y, entity_z; if(!get_NBT_value(entity, "x", &entity_x) || !get_NBT_value(entity, "y", &entity_y) || !get_NBT_value(entity, "z", &entity_z)) { continue; } //Check for mathing blocktype and ID if(block == BLOCK_CHEST && id == "Chest") { if(x == entity_x && y == entity_y && z == entity_z) { entityExists = true; theEntity = entity; existingID = i; break; } } } } //End For entitylist //Generate struct theEntity = new NBT_struct; NBT_value value; //Push ID value.type = TAG_STRING; value.name = "id"; std::string *name = new std::string; value.value = (void *)name; *(std::string *)value.value = "Chest"; theEntity->values.push_back(value); //Position value.type = TAG_INT; value.name = "x"; value.value = (void *)new int; *(int *)value.value = x; theEntity->values.push_back(value); value.name = "y"; value.value = (void *)new int; *(int *)value.value = y; theEntity->values.push_back(value); value.name = "z"; value.value = (void *)new int; *(int *)value.value = z; theEntity->values.push_back(value); //Put special chest items if(block == BLOCK_CHEST) { NBT_list *newlist = get_NBT_list(&newObject, "Items"); if(!newlist) { //std::cout << "Items not found!" << std::endl; return curpos; } NBT_list itemlist; itemlist.name = "Items"; itemlist.tagId = TAG_COMPOUND; itemlist.length = newlist->length; itemlist.items = (void **)new NBT_struct *[itemlist.length]; NBT_struct **structlist = (NBT_struct **)itemlist.items; for(int i = 0; i < itemlist.length; i++) { structlist[i] = new NBT_struct; char type_char; sint16 type_sint16; //Generate struct value.type = TAG_BYTE; value.name = "Count"; get_NBT_value((NBT_struct *)((NBT_struct **)newlist->items)[i], "Count", &type_char); value.value = (void *)new char; *(char *)value.value = type_char; structlist[i]->values.push_back(value); value.type = TAG_BYTE; value.name = "Slot"; get_NBT_value((NBT_struct *)((NBT_struct **)newlist->items)[i], "Slot", &type_char); value.value = (void *)new char; *(char *)value.value = type_char; structlist[i]->values.push_back(value); value.type = TAG_SHORT; value.name = "Damage"; get_NBT_value((NBT_struct *)((NBT_struct **)newlist->items)[i], "Damage", &type_sint16); value.value = (void *)new sint16; *(sint16 *)value.value = type_sint16; structlist[i]->values.push_back(value); value.type = TAG_SHORT; value.name = "id"; get_NBT_value((NBT_struct *)((NBT_struct **)newlist->items)[i], "id", &type_sint16); value.value = (void *)new sint16; *(sint16 *)value.value = type_sint16; structlist[i]->values.push_back(value); } theEntity->lists.push_back(itemlist); } //If entity doesn't exist in the list, resize the list to fit it in if(!entityExists) { //ToDo: try this! NBT_struct **newlist = new NBT_struct *[entitylist->length+1]; NBT_struct **oldlist = (NBT_struct **)entitylist->items; uint8 *structbuffer = new uint8[ALLOCATE_NBTFILE]; for(int i = 0; i < entitylist->length; i++) { newlist[i] = new NBT_struct; dumpNBT_struct(oldlist[i],structbuffer); TAG_Compound(structbuffer, newlist[i],true); freeNBT_struct(oldlist[i]); oldlist[i] = NULL; } delete [] structbuffer; entitylist->length++; entitylist->items = (void **)newlist; delete [] (NBT_struct **)oldlist; newlist[entitylist->length-1] = theEntity; } //If item exists, replace the old with the new else { //Destroy old entitylist NBT_struct **oldlist = (NBT_struct **)entitylist->items; freeNBT_struct(oldlist[existingID]); //Replace with the new oldlist[existingID] = theEntity; } //Mark chunk as changed Map::get().mapChanged[chunkID] = true; } //If entity exists } //If loaded map //Send complex entity packet to others if(theEntity) { uint8 *structdump = new uint8[ALLOCATE_NBTFILE]; uint8 *packetData = new uint8[ALLOCATE_NBTFILE]; int dumped = dumpNBT_struct(theEntity, structdump); uLongf written = ALLOCATE_NBTFILE; z_stream zstream2; zstream2.zalloc = Z_NULL; zstream2.zfree = Z_NULL; zstream2.opaque = Z_NULL; zstream2.next_out = &packetData[13]; zstream2.next_in = structdump; zstream2.avail_in = dumped; zstream2.avail_out = written; zstream2.total_out = 0; zstream2.total_in = 0; deflateInit2(&zstream2, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15+MAX_WBITS, 8, Z_DEFAULT_STRATEGY); if(int state=deflate(&zstream2,Z_FULL_FLUSH)!=Z_OK) { std::cout << "Error in deflate: " << state << std::endl; deflateEnd(&zstream2); } else { written = zstream2.total_out; packetData[0] = 0x3b; //Complex Entities putSint32(&packetData[1],x); putSint16(&packetData[5],y); putSint32(&packetData[7],z); putSint16(&packetData[11], (sint16)written); user->sendAll((uint8 *)&packetData[0], 13+written); } delete [] packetData; delete [] structdump; } return curpos; }
void PacketHandler::player_block_placement(uint8 *data, User *user) { int curpos = 0; int orig_x, orig_y, orig_z; bool change = false; int blockID = getSint16(&data[curpos]); curpos += 2; int x = orig_x = getSint32(&data[curpos]); curpos += 4; int y = orig_y = (char)data[curpos]; curpos++; int z = orig_z = getSint32(&data[curpos]); curpos += 4; int direction = (char)data[curpos]; curpos++; //Invalid y value if(y > 127 || y < 0) { //std::cout << blockID << " (" << x << "," << (int)y_orig << "," << z << ") " << direction << std::endl; return; } //std::cout << blockID << " (" << x << "," << (int)y_orig << "," << z << ")" << direction << std::endl; uint8 block; uint8 metadata; Map::get().getBlock(x, y, z, &block, &metadata); switch(direction) { case 0: y--; break; case 1: y++; break; case 2: z--; break; case 3: z++; break; case 4: x--; break; case 5: x++; break; } uint8 block_direction; uint8 metadata_direction; Map::get().getBlock(x, y, z, &block_direction, &metadata_direction); // Check liquid physics Physics::get().checkSurrounding(vec(x, y, z)); //If placing normal block and current block is empty if(blockID < 0xff && blockID != -1 && (block_direction == BLOCK_AIR || block_direction == BLOCK_WATER || block_direction == BLOCK_STATIONARY_WATER || block_direction == BLOCK_LAVA || block_direction == BLOCK_STATIONARY_LAVA)) { // DO NOT place a block if block is ... if(block != BLOCK_WORKBENCH && block != BLOCK_FURNACE && block != BLOCK_BURNING_FURNACE && block != BLOCK_CHEST && block != BLOCK_JUKEBOX) change = true; //std::cout << "Placing over " << (int)block_direction << std::endl; } if(block == BLOCK_SNOW || block == BLOCK_TORCH) //If snow or torch, overwrite { change = true; x = orig_x; y = orig_y; z = orig_z; } //Door status change if((block == BLOCK_WOODEN_DOOR) || (block == BLOCK_IRON_DOOR)) { change = true; blockID = block; //Toggle door state if(metadata&0x4) metadata &= (0x8|0x3); else metadata |= 0x4; uint8 metadata2, block2; int modifier = (metadata&0x8) ? -1 : 1; x = orig_x; y = orig_y; z = orig_z; Map::get().getBlock(x, y+modifier, z, &block2, &metadata2); if(block2 == block) { metadata2 = metadata; if(metadata&0x8) metadata2 &= (0x7); else metadata2 |= 0x8; Map::get().setBlock(x, y+modifier, z, block2, metadata2); Map::get().sendBlockChange(x, y+modifier, z, blockID, metadata2); } } // Check if player is standing there double intX, intZ, fracX, fracZ; // Check Y coordinate if(y == user->pos.y || y-1 == user->pos.y) { fracX = std::abs(std::modf(user->pos.x, &intX)); fracZ = std::abs(std::modf(user->pos.z, &intZ)); // Mystics intX--; intZ--; // Optimized version of the code below if((z == intZ || (z == intZ+1 && fracZ < 0.30) || (z == intZ-1 && fracZ > 0.70)) && (x == intX || (x == intX+1 && fracZ < 0.30) || (x == intX-1 && fracX > 0.70))) change = false; } if(blockID == BLOCK_TORCH || blockID == BLOCK_REDSTONE_TORCH_OFF || blockID == BLOCK_REDSTONE_TORCH_ON) { switch(direction) { case 0: case 1: metadata = 5; break; case 2: metadata = 4; break; case 3: metadata = 3; break; case 4: metadata = 1; break; case 5: metadata = 2; break; } } if(change) { Map::get().setBlock(x, y, z, blockID, metadata); Map::get().sendBlockChange(x, y, z, blockID, metadata); if(blockID == BLOCK_WATER || blockID == BLOCK_STATIONARY_WATER || blockID == BLOCK_LAVA || blockID == BLOCK_STATIONARY_LAVA) Physics::get().addSimulation(vec(x, y, z)); } }
int PacketHandler::player_inventory(User *user) { if(user->buffer.size() < 14) return PACKET_NEED_MORE_DATA; int curpos = 0; unsigned int i; //Read inventory type (-1,-2 or -3) uint8 tmpIntArray[4] = {0}; for(i = 0; i < 4; i++) tmpIntArray[i] = user->buffer[curpos+i]; int type = getSint32(&tmpIntArray[0]); curpos += 4; uint8 tmpShortArray[2] = {0}; for(i = 0; i < 2; i++) tmpShortArray[i] = user->buffer[curpos+i]; int count = getSint16(&tmpShortArray[0]); curpos += 2; int items = 0; Item *slots = NULL; items = count; switch(type) { //Main inventory case -1: //items = 36; memset(user->inv.main, 0, sizeof(Item)*36); slots = (Item *)&user->inv.main; break; //Equipped armour case -3: //items = 4; memset(user->inv.equipped, 0, sizeof(Item)*4); slots = (Item *)&user->inv.equipped; break; //Crafting slots case -2: //items = 4; memset(user->inv.crafting, 0, sizeof(Item)*4); slots = (Item *)&user->inv.crafting; break; } if(user->buffer.size() < (unsigned int)6+2*items) return PACKET_NEED_MORE_DATA; for(i = 0; i < (unsigned int)items; i++) { int j = 0; for(j = 0; j < 2; j++) tmpShortArray[j] = user->buffer[curpos+j]; int item_id = getSint16(&tmpShortArray[0]); curpos += 2; if(user->buffer.size() < curpos+(items-i-1)*2) return PACKET_NEED_MORE_DATA; if(item_id != -1) { if(user->buffer.size()-curpos < (items-i-1)*2+3) return PACKET_NEED_MORE_DATA; uint8 numberOfItems = user->buffer[curpos]; curpos++; for(j = 0; j < 2; j++) tmpShortArray[j] = user->buffer[curpos+j]; int health = getSint16(&tmpShortArray[0]); curpos += 2; //Save to user inventory slots[i].type = item_id; slots[i].count = numberOfItems; slots[i].health = health; } } //std::cout << "Got items type " << type << std::endl; //Package completely received, remove from buffer user->buffer.erase(user->buffer.begin(), user->buffer.begin()+curpos); return curpos; }
luabridge::LuaRef CLuaBinary::getStruct(luabridge::LuaRef objAttr) { assert(objAttr.isTable()); DataType emType; int iSize = Q_INIT_NUMBER; std::string strName; luabridge::LuaRef objVal = luabridge::newTable(m_pLua); for (int i = 1; i <= objAttr.length(); i++) { luabridge::LuaRef objTmp = objAttr[i]; if (!objTmp.isTable() || STATTRTAB_MINLENS > objTmp.length()) { break; } luabridge::LuaRef objChildStAttr = getStructAttr(objTmp, strName, emType, iSize); switch(emType) { case DTYPE_SINT8: { objVal[strName] = getSint8(); } break; case DTYPE_UINT8: { objVal[strName] = getUint8(); } break; case DTYPE_BOOL: { objVal[strName] = getBool(); } break; case DTYPE_SINT16: { objVal[strName] = getSint16(); } break; case DTYPE_UINT16: { objVal[strName] = getUint16(); } break; case DTYPE_SINT32: { objVal[strName] = getSint32(); } break; case DTYPE_UINT32: { objVal[strName] = getUint32(); } break; case DTYPE_SINT64: { objVal[strName] = getSint64(); } break; case DTYPE_UINT64: { objVal[strName] = getUint64(); } break; case DTYPE_FLOAT: { objVal[strName] = getFloat(); } break; case DTYPE_DOUBLE: { objVal[strName] = getDouble(); } break; case DTYPE_STRING: { std::string strVal = getString(); objVal[strName] = strVal; skipRead((unsigned int)(iSize - (strVal.size() + 1))); } break; case DTYPE_BYTE: { objVal[strName] = getByte(iSize); } break; case DTYPE_STRUCT: { objVal[strName] = getStruct(objChildStAttr); } break; case DTYPE_SKIP: { if (iSize > Q_INIT_NUMBER) { skipRead(iSize); } } break; default: break; } } return objVal; }