MapMgr* InstanceMgr::GetInstance(uint32 MapId, uint32 InstanceId) { Instance * in; InstanceMap::iterator itr; InstanceMap * instancemap; MapInfo * inf = WorldMapInfoStorage.LookupEntry(MapId); // we can *never* teleport to maps without a mapinfo. if( inf == NULL || MapId >= NUM_MAPS ) return NULLMAPMGR; // single-instance maps never go into the instance set. if( inf->type == INSTANCE_NULL ) return m_singleMaps[MapId]; m_mapLock.Acquire(); instancemap = m_instances[MapId]; if(instancemap != NULL) { // check our saved instance id. see if its valid, and if we can join before trying to find one. itr = instancemap->find(InstanceId); if(itr != instancemap->end()) { if(itr->second->m_mapMgr) { m_mapLock.Release(); return itr->second->m_mapMgr; } } // iterate over our instances, and see if any of them are owned/joinable by him. for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; // this is our instance. if(in->m_mapMgr == NULL) { // create the actual instance. in->m_mapMgr = _CreateInstance(in); m_mapLock.Release(); return in->m_mapMgr; } else { // instance is already created. m_mapLock.Release(); return in->m_mapMgr; } } } // if we're here, it means there are no instances on that map, or none of the instances on that map are joinable // by this player. m_mapLock.Release(); return NULLMAPMGR; }
void InstanceMgr::_CreateMap(uint32 mapid) { if( mapid >= NUM_MAPS ) return; MapInfo* inf = WorldMapInfoStorage.LookupEntry(mapid); if(!inf || m_maps[mapid]) return; m_maps[mapid] = new Map(mapid, inf); if(inf->type == INSTANCE_NULL) { // we're a continent, create the instance. _CreateInstance(mapid, GenerateInstanceID()); } }
void InstanceMgr::_CreateMap(uint32 mapid) { if (mapid >= NUM_MAPS) return; MapInfo const* inf = sMySQLStore.GetWorldMapInfo(mapid); if (inf == nullptr) return; if (m_maps[mapid] != NULL) return; m_maps[mapid] = new Map(mapid, inf); if (inf->type == INSTANCE_NULL) { // we're a continent, create the instance. _CreateInstance(mapid, GenerateInstanceID()); } }
MapMgr* InstanceMgr::GetInstance(Object* obj) { Player* plr; Instance* in; InstanceMap::iterator itr; InstanceMap* instancemap; MapInfo* inf = WorldMapInfoStorage.LookupEntry(obj->GetMapId()); // we can *never* teleport to maps without a mapinfo. if(inf == NULL || obj->GetMapId() >= NUM_MAPS) return NULL; if(obj->IsPlayer()) { // players can join instances based on their groups/solo status. plr = TO< Player* >(obj); // single-instance maps never go into the instance set. if(inf->type == INSTANCE_NULL) return m_singleMaps[obj->GetMapId()]; m_mapLock.Acquire(); instancemap = m_instances[obj->GetMapId()]; if(instancemap != NULL) { // check our saved instance id. see if its valid, and if we can join before trying to find one. itr = instancemap->find(obj->GetInstanceID()); if(itr != instancemap->end()) { if(itr->second->m_mapMgr == NULL) { itr->second->m_mapMgr = _CreateInstance(itr->second); } if(itr->second->m_mapMgr) { m_mapLock.Release(); return itr->second->m_mapMgr; } } // iterate over our instances, and see if any of them are owned/joinable by him. for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; uint32 difficulty; if(in->m_mapInfo->type == INSTANCE_RAID) difficulty = plr->GetRaidDifficulty(); else difficulty = plr->GetDungeonDifficulty(); if(in->m_difficulty == difficulty && PlayerOwnsInstance(in, plr)) { // this is our instance. if(in->m_mapMgr == NULL) { /*if(plr->m_TeleportState == 1) { // the player is loading. boot him out to the entry point, we don't want to spam useless instances on startup. m_mapLock.Release(); return NULL; }*/ // create the actual instance. in->m_mapMgr = _CreateInstance(in); m_mapLock.Release(); return in->m_mapMgr; } else { // instance is already created. m_mapLock.Release(); return in->m_mapMgr; } } } } // if we're here, it means there are no instances on that map, or none of the instances on that map are joinable // by this player. m_mapLock.Release(); return NULL; } else { // units are *always* limited to their set instance ids. if(inf->type == INSTANCE_NULL) return m_singleMaps[obj->GetMapId()]; m_mapLock.Acquire(); instancemap = m_instances[obj->GetMapId()]; if(instancemap) { itr = instancemap->find(obj->GetInstanceID()); if(itr != instancemap->end()) { // we never create instances just for units. m_mapLock.Release(); return itr->second->m_mapMgr; } } // instance is non-existent (shouldn't really happen for units...) m_mapLock.Release(); return NULL; } }
MapMgr* InstanceMgr::GetInstance(Object* obj) { Player* plr = NULL; InstanceMap::iterator itr; InstanceMap * instancemap = NULL; MapInfo * inf = NULL; inf = WorldMapInfoStorage.LookupEntry(obj->GetMapId()); // we can *never* teleport to maps without a mapinfo. if( inf == NULL || obj->GetMapId() >= NUM_MAPS ) return NULLMAPMGR; if( obj->IsPlayer() ) { // players can join instances based on their groups/solo status. plr = TO_PLAYER( obj ); // single-instance maps never go into the instance set. if( inf->type == INSTANCE_NULL ) return m_singleMaps[obj->GetMapId()]; m_mapLock.Acquire(); instancemap = m_instances[obj->GetMapId()]; if(instancemap != NULL) { // check our saved instance id. see if its valid, and if we can join before trying to find one. itr = instancemap->find(obj->GetInstanceID()); if(itr != instancemap->end()) { if(itr->second) { //we have an instance,but can we enter it? uint8 owns = PlayerOwnsInstance( itr->second, plr ); if( owns >= OWNER_CHECK_OK ) { //wakeup call for saved instances if(itr->second->m_mapMgr == NULL) itr->second->m_mapMgr = _CreateInstance(itr->second); if(owns == OWNER_CHECK_SAVED_OK && !itr->second->m_mapMgr->HasPlayers()) { if(plr->GetGroup()) itr->second->m_creatorGroup = plr->GetGroupID(); } m_mapLock.Release(); return itr->second->m_mapMgr; } } } // iterate over our instances, and see if any of them are owned/joinable by him. for(itr = instancemap->begin(); itr != instancemap->end(); itr++) { // Is this our instance? uint8 owns = PlayerOwnsInstance(itr->second, plr); if(owns >= OWNER_CHECK_OK ) { //wakeup call for saved instances if(itr->second->m_mapMgr == NULL) itr->second->m_mapMgr = _CreateInstance(itr->second); if(owns == OWNER_CHECK_SAVED_OK && !itr->second->m_mapMgr->HasPlayers()) { if(plr->GetGroup()) itr->second->m_creatorGroup = plr->GetGroupID(); } m_mapLock.Release(); return itr->second->m_mapMgr; } else DEBUG_LOG("InstanceMgr","Check failed %s", plr->GetName()); } } // if we're here, it means there are no instances on that map, or none of the instances on that map are joinable // by this player. m_mapLock.Release(); return NULLMAPMGR; } else { // units are *always* limited to their set instance ids. if(inf->type == INSTANCE_NULL) return m_singleMaps[obj->GetMapId()]; m_mapLock.Acquire(); instancemap = m_instances[obj->GetMapId()]; if(instancemap != NULL) { itr = instancemap->find(obj->GetInstanceID()); if(itr != instancemap->end()) { // we never create instances just for units. m_mapLock.Release(); return itr->second->m_mapMgr; } } // instance is non-existant (shouldn't really happen for units...) m_mapLock.Release(); return NULLMAPMGR; } }
uint32 InstanceMgr::PreTeleport(uint32 mapid, Player* plr, uint32 instanceid) { // preteleport is where all the magic happens :P instance creation, etc. MapInfo * inf = LimitedMapInfoStorage.LookupEntry(mapid); MapEntry* map = dbcMap.LookupEntry(mapid); InstanceMap * instancemap; Instance * in = NULL; //is the map vaild? if(inf == NULL || mapid >= NUM_MAPS) return INSTANCE_ABORT_NOT_FOUND; // main continent check. if(inf->type == INSTANCE_NULL) // we can check if the destination world server is online or not and then cancel them before they load. return (m_singleMaps[mapid] != NULL) ? INSTANCE_OK : INSTANCE_ABORT_NOT_FOUND; // shouldn't happen if(inf->type == INSTANCE_PVP) return INSTANCE_ABORT_NOT_FOUND; if(map->israid()) // check that heroic mode is available if the player has requested it. { if(plr->iRaidType > 1 && inf->type != INSTANCE_MULTIMODE) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; } else if(plr->iInstanceType && inf->type != INSTANCE_MULTIMODE) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; //do we need addition raid/heroic checks? Group * pGroup = plr->GetGroup() ; if( !plr->triggerpass_cheat ) { // players without groups cannot enter raid instances (no soloing them:P) if( pGroup == NULL && (map->israid() || inf->type == INSTANCE_MULTIMODE)) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; //and has the required level if( plr->getLevel() < 80) { if(!map->israid()) { //otherwise we still need to be lvl 70/80 for heroic. if( plr->iInstanceType && plr->getLevel() < uint32(inf->HasFlag(WMI_INSTANCE_XPACK_02) ? 80 : 70)) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; } else //otherwise we still need to be lvl 70/80 for heroic. if( plr->iRaidType > 1 && plr->getLevel() < uint32(inf->HasFlag(WMI_INSTANCE_XPACK_02) ? 80 : 70)) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; //and we might need a key too. bool reqkey = (inf->heroic_key[0] || inf->heroic_key[1])? true : false; bool haskey = (plr->GetItemInterface()->GetItemCount(inf->heroic_key[0], false) || plr->GetItemInterface()->GetItemCount(inf->heroic_key[1], false))? true : false; if(reqkey && !haskey) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; } } // if we are here, it means: // 1) we're a non-raid instance // 2) we're a raid instance, and the person is in a group. // so, first we have to check if they have an instance on this map already, if so, allow them to teleport to that. // next we check if there is a saved instance belonging to him. // otherwise, we can create them a new one. m_mapLock.Acquire(); //find all instances for our map instancemap = m_instances[mapid]; if(instancemap) { InstanceMap::iterator itr; // do we have a specific instance id we should enter (saved or active). // don't bother looking for saved instances, if we had one we found it in areatrigger.cpp if(instanceid != 0) { itr = instancemap->find(instanceid); if(itr != instancemap->end()) { in = itr->second; //we have an instance,but can we enter it? uint8 owns = PlayerOwnsInstance( in, plr ); if( owns >= OWNER_CHECK_OK ) { // If the map is active and has players if(in->m_mapMgr && in->m_mapMgr->HasPlayers() && !plr->triggerpass_cheat) { //check if combat is in progress if( in->m_mapMgr->IsCombatInProgress()) { m_mapLock.Release(); return INSTANCE_ABORT_ENCOUNTER; } // check if we are full if( in->m_mapMgr->GetPlayerCount() >= inf->playerlimit ) { m_mapLock.Release(); return INSTANCE_ABORT_FULL; } } uint32 plrdiff = map->israid() ? plr->iRaidType : plr->iInstanceType; if(in->m_difficulty == plrdiff) { //wakeup call for saved instances if(!in->m_mapMgr) in->m_mapMgr = _CreateInstance(in); if(owns == OWNER_CHECK_SAVED_OK && !in->m_mapMgr->HasPlayers()) { if(plr->GetGroup()) in->m_creatorGroup = plr->GetGroupID(); } m_mapLock.Release(); return INSTANCE_OK; } else { m_mapLock.Release(); return INSTANCE_ABORT_TOO_MANY; } } else DEBUG_LOG("InstanceMgr","Check failed %s, return code %u",plr->GetName(), owns); } m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } else { // search all active instances and see if we have one here. for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; //we have an instance,but do we own it? uint8 owns = PlayerOwnsInstance(in, plr); if( owns >= OWNER_CHECK_OK ) { // check the player count and in combat status. if(in->m_mapMgr && in->m_mapMgr->HasPlayers() && !plr->triggerpass_cheat) { if( in->m_mapMgr->IsCombatInProgress()) { m_mapLock.Release(); return INSTANCE_ABORT_ENCOUNTER; } // check if we are full if( in->m_mapMgr->GetPlayerCount() >= inf->playerlimit ) { m_mapLock.Release(); return INSTANCE_ABORT_FULL; } } uint32 plrdiff = map->israid() ? plr->iRaidType : plr->iInstanceType; if(in->m_difficulty == plrdiff) { //wakeup call for saved instances if(!in->m_mapMgr) in->m_mapMgr = _CreateInstance(in); if(owns == OWNER_CHECK_SAVED_OK && !in->m_mapMgr->HasPlayers()) { if(plr->GetGroup()) in->m_creatorGroup = plr->GetGroupID(); } // found our instance, allow him in. m_mapLock.Release(); return INSTANCE_OK; } } else DEBUG_LOG("InstanceMgr","Check failed %s, return code %u",plr->GetName(), owns); } } } else { if(instanceid != 0) { // wtf, how can we have an instance_id for a mapid which doesn't even exist? m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } // this mapid hasn't been added yet, so we gotta create the hashmap now. m_instances[mapid] = new InstanceMap; instancemap = m_instances[mapid]; } // if we're here, it means we need to create a new instance. bool raid = map->israid(); in = new Instance; in->m_creation = UNIXTIME; in->m_expiration = (raid ? UNIXTIME + inf->cooldown : 0); // expire time 0 is 10 minutes after last player leaves in->m_creatorGuid = plr->GetLowGUID(); in->m_creatorGroup = (pGroup ? pGroup->GetID() : 0); in->m_difficulty = (raid ? plr->iRaidType : plr->iInstanceType); in->m_instanceId = GenerateInstanceID(); in->m_mapId = mapid; in->m_mapMgr = NULLMAPMGR; // always start off without a map manager, it is created in _CreateInstance(in) //crash fix; GM's without group will start up raid instances as if they where nonraids //this to avoid exipring check, this is mainly for developers purpose; GM's should NOT invite any players here! if( plr->triggerpass_cheat && !plr->GetGroup() && raid) { const char * message = "Started this instance for development purposes only, do not invite players!!"; sEventMgr.AddEvent( plr, &Player::_Warn, message, EVENT_UNIT_SENDMESSAGE, 5000, 1, 0); } in->m_mapInfo = inf; in->m_dbcMap = map; in->m_isBattleground = false; plr->SetInstanceID(in->m_instanceId); DEBUG_LOG("InstanceMgr", "Prepared new %s %u for player %u and group %u on map %u with difficulty %u. (%u)", raid ? "Raid" : "Instance" ,in->m_instanceId, in->m_creatorGuid, in->m_creatorGroup, in->m_mapId, in->m_difficulty, in->m_instanceId); // apply it in the instance map instancemap->insert( InstanceMap::value_type( in->m_instanceId, in ) ); // create the actual instance (if we don't GetInstance() won't be able to access it). in->m_mapMgr = _CreateInstance(in); // instance created ok, i guess? return the ok for him to transport. m_mapLock.Release(); return INSTANCE_OK; }
MapMgrPointer InstanceMgr::GetInstance(ObjectPointer obj) { PlayerPointer plr; Instance * in; InstanceMap::iterator itr; InstanceMap * instancemap; MapInfo * inf = WorldMapInfoStorage.LookupEntry(obj->GetMapId()); // we can *never* teleport to maps without a mapinfo. if( inf == NULL || obj->GetMapId() >= NUM_MAPS ) return NULLMAPMGR; if( obj->IsPlayer() ) { // players can join instances based on their groups/solo status. plr = TO_PLAYER( obj ); // single-instance maps never go into the instance set. if( inf->type == INSTANCE_NULL ) return m_singleMaps[obj->GetMapId()]; m_mapLock.Acquire(); instancemap = m_instances[obj->GetMapId()]; if(instancemap != NULL) { // check our instance_id, which we saved before in Player::_Relocate uint32 plr_instanceID = obj->GetInstanceID(); itr = instancemap->find(plr_instanceID); if(itr != instancemap->end()) { in = itr->second; if(in && in->m_mapMgr) { m_mapLock.Release(); return in->m_mapMgr; } } // iterate over our instances, and see if any of them are owned/joinable by him. for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; // Is this our instance? uint8 poinst = PlayerOwnsInstance(in, plr); if(poinst >= OWNER_CHECK_OK ) { //Has it been created yet? if(in->m_mapMgr == NULL) { // create the actual instance. in->m_mapMgr = _CreateInstance(in); m_mapLock.Release(); // first one to enter, set the group instance ID if( plr->GetGroup() && !plr->GetSession()->HasGMPermissions() ) plr->GetGroup()->SetGroupInstanceID(in->m_instanceId); return in->m_mapMgr; } else // instance has found and verfied; us it. { if( poinst != OWNER_CHECK_GM_INSIDE && in->m_mapMgr->HasPlayers() && plr->GetGroup() && plr->GetGroup()->GetGroupInstanceID() != in->m_instanceId ) { Log.Warning("InstanceMgr","Reset GroupInstanceID for existing instance %u [%s] , old_ID = %u, new_ID = %u", in->m_mapId, in->m_mapInfo->name, plr->GetGroup()->GetGroupInstanceID(), in->m_instanceId ); plr->GetGroup()->SetGroupInstanceID(in->m_instanceId); } else if(in->m_mapMgr->HasPlayers() && plr->GetGroup() && plr->GetGroup()->GetGroupInstanceID() != in->m_instanceId) { Log.Warning("InstanceMgr","Forced GroupInstanceID for instance %u [%s] started by GM, old_ID = %u, new_ID = %u", in->m_mapId, in->m_mapInfo->name, plr->GetGroup()->GetGroupInstanceID(), in->m_instanceId ); plr->GetGroup()->SetGroupInstanceID(in->m_instanceId); } m_mapLock.Release(); return in->m_mapMgr; } } else DEBUG_LOG("InstanceMgr","Check failed %s",plr->GetName()); } } // if we're here, it means there are no instances on that map, or none of the instances on that map are joinable // by this player. m_mapLock.Release(); return NULLMAPMGR; } else { // units are *always* limited to their set instance ids. if(inf->type == INSTANCE_NULL) return m_singleMaps[obj->GetMapId()]; m_mapLock.Acquire(); instancemap = m_instances[obj->GetMapId()]; if(instancemap) { itr = instancemap->find(obj->GetInstanceID()); if(itr != instancemap->end()) { // we never create instances just for units. m_mapLock.Release(); return itr->second->m_mapMgr; } } // instance is non-existant (shouldn't really happen for units...) m_mapLock.Release(); return NULLMAPMGR; } }
uint32 InstanceMgr::PreTeleport(uint32 mapid, PlayerPointer plr, uint32 instanceid) { // preteleport is where all the magic happens :P instance creation, etc. MapInfo * inf = WorldMapInfoStorage.LookupEntry(mapid); Group * pGroup = plr->GetGroup() ; InstanceMap * instancemap; Instance * in; if(inf == NULL || mapid>=NUM_MAPS) return INSTANCE_ABORT_NOT_FOUND; // main continent check. if(inf->type == INSTANCE_NULL) { // this will be useful when clustering comes into play. // we can check if the destination world server is online or not and then cancel them before they load. return (m_singleMaps[mapid] != NULL) ? INSTANCE_OK : INSTANCE_ABORT_NOT_FOUND; } // shouldn't happen if(inf->type==INSTANCE_PVP) return INSTANCE_ABORT_NOT_FOUND; if( !plr->triggerpass_cheat ) { // players without groups cannot enter raid instances (no soloing them:P) if( pGroup == NULL && (inf->type == INSTANCE_RAID || inf->type == INSTANCE_MULTIMODE)) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // check that heroic mode is available if the player has requested it. if(plr->iInstanceType && inf->type != INSTANCE_MULTIMODE) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; } // if we are here, it means: // 1) we're a non-raid instance // 2) we're a raid instance, and the person is in a group. // so, first we have to check if they have an instance on this map already, if so, allow them to teleport to that. // otherwise, we can create them a new one. m_mapLock.Acquire(); instancemap = m_instances[mapid]; if(instancemap) { InstanceMap::iterator itr; if(instanceid != 0) { //try to find our instance in ones active now. itr = instancemap->find(instanceid); if(itr != instancemap->end()) { Instance *inn = itr->second; if( PlayerOwnsInstance( inn, plr ) >= OWNER_CHECK_OK ) { m_mapLock.Release(); return INSTANCE_OK; } } //There are no active maps, re-check if this concerns a saved instance. Instance * saved_in = sInstanceMgr.GetSavedInstance( mapid, plr->GetLowGUID() ); if( saved_in && saved_in->m_instanceId == instanceid ) { if ( PlayerOwnsInstance( saved_in, plr ) >= OWNER_CHECK_OK ) { m_mapLock.Release(); return INSTANCE_OK; } } m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } else { // search all active instances and see if we have one here. for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if(PlayerOwnsInstance(in, plr) >= OWNER_CHECK_OK ) { m_mapLock.Release(); // check the player count and in combat status. if(in->m_mapMgr && in->m_mapMgr->HasPlayers() && !plr->triggerpass_cheat) { if( in->m_mapMgr->IsCombatInProgress()) return INSTANCE_ABORT_ENCOUNTER; // check if we are full if( in->m_mapMgr->GetPlayerCount() >= inf->playerlimit ) return INSTANCE_ABORT_FULL; } // found our instance, allow him in. return INSTANCE_OK; } else DEBUG_LOG("InstanceMgr","Check failed %s",plr->GetName()); } } } else { if(instanceid != 0) { return INSTANCE_ABORT_NOT_FOUND; } // gotta create the hashmap. m_instances[mapid] = new InstanceMap; instancemap = m_instances[mapid]; } // if we're here, it means we need to create a new instance. in = new Instance; in->m_creation = UNIXTIME; in->m_expiration = (inf->type == INSTANCE_NONRAID) ? 0 : UNIXTIME + inf->cooldown; // expire time 0 is 10 minutes after last player leaves in->m_creatorGuid = pGroup ? 0 : plr->GetLowGUID(); // creator guid is 0 if its owned by a group. in->m_creatorGroup = pGroup ? pGroup->GetID() : 0; in->m_difficulty = plr->iInstanceType; in->m_instanceId = GenerateInstanceID(); in->m_mapId = mapid; in->m_mapMgr = NULLMAPMGR; // always start off without a map manager, it is created in GetInstance() //crash fix; GM's without group will start up raid instances as if they where nonraids //this to avoid exipring check, this is mainly for developers purpose; GM's should NOT invite any players here! if( plr->triggerpass_cheat && !plr->GetGroup() && inf->type == INSTANCE_RAID) { inf->type = INSTANCE_NONRAID; sGMLog.writefromsession(plr->GetSession(), "Started a raid instance %d [%s] as non_raid instance.", mapid, inf->name); DEBUG_LOG("InstanceMgr","Started a raid instance %d [%s] as non_raid instance.", mapid, inf->name); } in->m_mapInfo = inf; in->m_isBattleground=false; plr->SetInstanceID(in->m_instanceId); if( plr->GetGroup() && !plr->GetSession()->HasGMPermissions())//GM should not set the instanceID pGroup->SetGroupInstanceID(in->m_instanceId); DEBUG_LOG("InstanceMgr", "Prepared new instance %u for player %u and group %u on map %u. (%u)",in->m_instanceId, in->m_creatorGuid, in->m_creatorGroup, in->m_mapId, in->m_instanceId); // apply it in the instance map instancemap->insert( InstanceMap::value_type( in->m_instanceId, in ) ); // create the actual instance (if we don't GetInstance() won't be able to access it). in->m_mapMgr = _CreateInstance(in); // instance created ok, i guess? return the ok for him to transport. m_mapLock.Release(); return INSTANCE_OK; }
STDAPI SHCoCreateInstance(LPCTSTR pszCLSID, const CLSID * pclsid, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID FAR* ppv) { HRESULT hres = ResultFromScode(REGDB_E_CLASSNOTREG); CLSID clsidT; TCHAR szClass[GUIDSTR_MAX+ARRAYSIZE(c_szInProcServer)]; if (pclsid) { if (!pszCLSID) { StringFromGUID2A(pclsid, szClass, ARRAYSIZE(szClass)); } } else { if (pszCLSID) { lstrcpy(szClass,pszCLSID); if (SUCCEEDED(SHCLSIDFromString(pszCLSID, &clsidT))) pclsid=&clsidT; } } if (pclsid) { LONG err; HKEY hkeyDll; IClassFactory *pCF; Assert(hres == ResultFromScode(REGDB_E_CLASSNOTREG)); lstrcat(szClass,c_szInProcServer); // Add "\InProcServer32" hres = _FindRegisteredClass(pclsid, &pCF); if (SUCCEEDED(hres)) { hres = pCF->lpVtbl->CreateInstance(pCF, pUnkOuter, riid, ppv); pCF->lpVtbl->Release(pCF); } else { if (g_hkcrCLSID && RegOpenKey(g_hkcrCLSID, szClass, &hkeyDll) == ERROR_SUCCESS) { TCHAR szDllName[MAX_PATH]; LONG cbValue = SIZEOF(szDllName); // 1 2 3 // 012345678901234567890123456789012345678 = nul is at 38! // "{12345678-1234-1234-1234-123456789012}" // szClass[38] = TEXT('\0'); // Get rid of "\InProcServer32" err = RegQueryValue(hkeyDll, NULL, szDllName, &cbValue); #ifdef WINNT // // On NT, we must check to ensure that this CLSID exists in // the list of approved CLSIDs that can be used in-process. // If not, we fail the creation with ERROR_ACCESS_DENIED. // We explicitly allow anything serviced by this DLL // if (err == ERROR_SUCCESS && NULL != g_hklmApprovedExt) { TCHAR szBuf[MAX_PATH]; // // Check to see if we are using this DLL // // BUGBUG Assumes no parameters in InProcServer32. We // should remove this assumption once we lose shellalt, // after which we can just lstrcpyn(,,<length of dll name>); LPCTSTR pszDllName = PathFindFileName(szDllName); if (lstrcmp(pszDllName, TEXT("shell32.dll")) && lstrcmp(pszDllName, TEXT("shellalt.dll"))) { DWORD dwType; TCHAR szValue[MAX_PATH]; DWORD cbSize = SIZEOF(szValue); if (ERROR_SUCCESS != RegQueryValueEx(g_hklmApprovedExt, szClass, 0, &dwType, (LPBYTE) szValue, &cbSize)) { hres = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); return hres; } } } #endif if (err == ERROR_SUCCESS) { TCHAR szThreadingModel[MAX_PATH]; BOOL fMultiThreadAware = FALSE; DWORD dwRegType; DWORD cbRead = SIZEOF(szThreadingModel); err = RegQueryValueEx(hkeyDll, c_szThreadingModel, NULL, &dwRegType, (LPBYTE)szThreadingModel, &cbRead); if (err == ERROR_SUCCESS && dwRegType == REG_SZ) { if (lstrcmpi(szThreadingModel, c_szApartment)==0 || lstrcmpi(szThreadingModel, c_szBoth)==0) { fMultiThreadAware = TRUE; } } // #define HACK_APARTMENT_ONLY_ASSERT #ifdef HACK_APARTMENT_ONLY_ASSERT if (!fMultiThreadAware) { _asm { int 3; } } Assert(fMultiThreadAware); hres = _CreateInstance(pclsid, szDllName, pUnkOuter, riid, ppv); #else if (fMultiThreadAware) { hres = _CreateInstance(pclsid, szDllName, pUnkOuter, riid, ppv); } else { Assert(hres == ResultFromScode(REGDB_E_CLASSNOTREG)); DebugMsg(DM_ERROR, TEXT("sh TR - SHCoCreateInstance !!! InProcServer32 (%s) does not support multi-threading"), szDllName); Assert(0); } #endif } RegCloseKey(hkeyDll); }