530 lines
16 KiB
C++
530 lines
16 KiB
C++
|
/*
|
||
|
** Command & Conquer Renegade(tm)
|
||
|
** Copyright 2025 Electronic Arts Inc.
|
||
|
**
|
||
|
** This program is free software: you can redistribute it and/or modify
|
||
|
** it under the terms of the GNU General Public License as published by
|
||
|
** the Free Software Foundation, either version 3 of the License, or
|
||
|
** (at your option) any later version.
|
||
|
**
|
||
|
** This program is distributed in the hope that it will be useful,
|
||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
** GNU General Public License for more details.
|
||
|
**
|
||
|
** You should have received a copy of the GNU General Public License
|
||
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
*** Confidential - Westwood Studios ***
|
||
|
***********************************************************************************************
|
||
|
* *
|
||
|
* Project Name : Commando *
|
||
|
* *
|
||
|
* $Archive:: /Commando/Code/Commando/shutdown.cpp $*
|
||
|
* *
|
||
|
* $Author:: Steve_t $*
|
||
|
* *
|
||
|
* $Modtime:: 10/16/02 11:11a $*
|
||
|
* *
|
||
|
* $Revision:: 104 $*
|
||
|
* *
|
||
|
*---------------------------------------------------------------------------------------------*
|
||
|
* Functions: *
|
||
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
|
||
|
#include "shutdown.h"
|
||
|
#include "wwmath.h"
|
||
|
#include "wwsaveload.h"
|
||
|
#include "ww3d.h"
|
||
|
#include "WWAudio.H"
|
||
|
#include "wwphys.h"
|
||
|
#include "debug.h"
|
||
|
#include "assets.h"
|
||
|
#include "ffactorylist.h"
|
||
|
#include "input.h"
|
||
|
#include "inputconfigmgr.h"
|
||
|
#include "gamemode.h"
|
||
|
//#include "gamesettings.h"
|
||
|
#include "miscutil.h"
|
||
|
#include "refcount.h"
|
||
|
#include "cnetwork.h"
|
||
|
#include "_globals.h"
|
||
|
#include "systemsettings.h"
|
||
|
#include "diagnostics.h"
|
||
|
#include "translatedb.h"
|
||
|
#include "pathmgr.h"
|
||
|
#include "renegadedialogmgr.h"
|
||
|
#include "campaign.h"
|
||
|
#include "diaglog.h"
|
||
|
#include "binkmovie.h"
|
||
|
//#include "helptext.h"
|
||
|
#include "init.h"
|
||
|
#include "serverfps.h"
|
||
|
#include "encyclopediamgr.h"
|
||
|
#include "playermanager.h"
|
||
|
#include "teammanager.h"
|
||
|
#include "bandwidthgraph.h"
|
||
|
#include "except.h"
|
||
|
#include "skinpackagemgr.h"
|
||
|
#include "modpackagemgr.h"
|
||
|
|
||
|
#include "dx8wrapper.h"
|
||
|
#include "pscene.h"
|
||
|
#include "systeminfolog.h"
|
||
|
#include "cpudetect.h"
|
||
|
#include "dx8caps.h"
|
||
|
#include "registry.h"
|
||
|
#include "specialbuilds.h"
|
||
|
#include <windows.h>
|
||
|
#include <lmcons.h> // UNLEN
|
||
|
extern SimpleFileFactoryClass RenegadeBaseFileFactory;
|
||
|
|
||
|
#define SYSTEM_INFO_LOG_DISABLE "SystemInfoLogDisable"
|
||
|
|
||
|
// These are copy-pasted from WWConfig
|
||
|
//extern const char *KEY_NAME_SETTINGS;
|
||
|
extern const char *VALUE_NAME_DYN_LOD;
|
||
|
extern const char *VALUE_NAME_STATIC_LOD;
|
||
|
extern const char *VALUE_NAME_DYN_SHADOWS;
|
||
|
const char *VALUE_NAME_PRELIT_MODE = "Prelit_Mode";
|
||
|
extern const char *VALUE_NAME_SHADOW_MODE;
|
||
|
extern const char *VALUE_NAME_STATIC_SHADOWS;
|
||
|
extern const char *VALUE_NAME_TEXTURE_RES;
|
||
|
const char *VALUE_NAME_SURFACE_EFFECT = "Surface_Effect_Detail";
|
||
|
extern const char *VALUE_NAME_PARTICLE_DETAIL;
|
||
|
const char *VALUE_NAME_TEXTURE_FILTER_MODE="Texture_Filter_Mode";
|
||
|
|
||
|
static void Get_Detail_String(StringClass& str)
|
||
|
{
|
||
|
str="";
|
||
|
RegistryClass registry (APPLICATION_SUB_KEY_NAME_SYSTEM_SETTINGS);
|
||
|
if (registry.Is_Valid ()) {
|
||
|
|
||
|
//
|
||
|
// Read the values from the registry
|
||
|
//
|
||
|
int dynamic_lod = registry.Get_Int (VALUE_NAME_DYN_LOD, 3000);
|
||
|
int static_lod = registry.Get_Int (VALUE_NAME_STATIC_LOD, 3000);
|
||
|
|
||
|
int dynamic_shadows = registry.Get_Int (VALUE_NAME_DYN_SHADOWS, 1);
|
||
|
int static_shadows = registry.Get_Int (VALUE_NAME_STATIC_SHADOWS, 1);
|
||
|
|
||
|
int texture_filter = registry.Get_Int (VALUE_NAME_TEXTURE_FILTER_MODE, TextureClass::TEXTURE_FILTER_BILINEAR);
|
||
|
int prelit_mode = registry.Get_Int (VALUE_NAME_PRELIT_MODE, WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE);
|
||
|
int shadow_mode = registry.Get_Int (VALUE_NAME_SHADOW_MODE, PhysicsSceneClass::SHADOW_MODE_BLOBS_PLUS);
|
||
|
int texture_red = registry.Get_Int (VALUE_NAME_TEXTURE_RES, 0);
|
||
|
int surface_effect = registry.Get_Int (VALUE_NAME_SURFACE_EFFECT, 1);
|
||
|
int particle_detail = registry.Get_Int (VALUE_NAME_PARTICLE_DETAIL, 1);
|
||
|
|
||
|
StringClass tmp;
|
||
|
tmp.Format("Dynamic LOD budget: %d\r\n",dynamic_lod);
|
||
|
str+=tmp;
|
||
|
tmp.Format("Static LOD budget: %d\r\n",static_lod);
|
||
|
str+=tmp;
|
||
|
|
||
|
str+="Shadow Mode: ";
|
||
|
switch (shadow_mode) {
|
||
|
case PhysicsSceneClass::SHADOW_MODE_NONE: str+="None\r\n"; break;
|
||
|
case PhysicsSceneClass::SHADOW_MODE_BLOBS: str+="Blobs\r\n"; break;
|
||
|
case PhysicsSceneClass::SHADOW_MODE_BLOBS_PLUS: str+="Blobs Plus\r\n"; break;
|
||
|
case PhysicsSceneClass::SHADOW_MODE_HARDWARE: str+="Hardware\r\n"; break;
|
||
|
default: str+="???\r\n"; break;
|
||
|
}
|
||
|
|
||
|
tmp.Format("Dynamic Shadows: %s\r\n",dynamic_shadows ? "On" : "Off");
|
||
|
str+=tmp;
|
||
|
tmp.Format("Static Shadows: %s\r\n",static_shadows ? "On" : "Off");
|
||
|
str+=tmp;
|
||
|
|
||
|
str+="Prelit Mode: ";
|
||
|
switch (prelit_mode) {
|
||
|
case WW3D::PRELIT_MODE_VERTEX: str+="Vertex\r\n"; break;
|
||
|
case WW3D::PRELIT_MODE_LIGHTMAP_MULTI_PASS: str+="Multipass\r\n"; break;
|
||
|
case WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE: str+="Multitexture\r\n"; break;
|
||
|
default: str+="???\r\n"; break;
|
||
|
}
|
||
|
tmp.Format("Texture Resolution: %d\r\n",texture_red);
|
||
|
str+=tmp;
|
||
|
|
||
|
tmp.Format("Surface Effects (0-2): %d\r\n",surface_effect);
|
||
|
str+=tmp;
|
||
|
|
||
|
tmp.Format("Particle Detail(0-2): %d\r\n",particle_detail);
|
||
|
str+=tmp;
|
||
|
|
||
|
str+="Texture Filter Mode: ";
|
||
|
switch (texture_filter) {
|
||
|
case TextureClass::TEXTURE_FILTER_BILINEAR: str+="Bilinear\r\n"; break;
|
||
|
case TextureClass::TEXTURE_FILTER_TRILINEAR: str+="Trilinear\r\n"; break;
|
||
|
case TextureClass::TEXTURE_FILTER_ANISOTROPIC: str+="Anisotropic\r\n"; break;
|
||
|
default: str+="???\r\n"; break;
|
||
|
}
|
||
|
|
||
|
tmp.Format("Screen UV Bias: %s\r\n",WW3D::Is_Screen_UV_Biased() ? "Enabled" : "Disabled");
|
||
|
str+=tmp;
|
||
|
|
||
|
// NPatch level
|
||
|
str+="NPatch level: ";
|
||
|
if (DX8Wrapper::Get_Current_Caps() && DX8Wrapper::Get_Current_Caps()->Support_NPatches()) {
|
||
|
if (WW3D::Get_NPatches_Level()<=1) {
|
||
|
str+="Disabled\r\n";
|
||
|
}
|
||
|
else {
|
||
|
tmp.Format("%d\r\n",WW3D::Get_NPatches_Level());
|
||
|
str+=tmp;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
str+="Not supported\r\n";
|
||
|
}
|
||
|
|
||
|
int w;
|
||
|
int h;
|
||
|
int bits;
|
||
|
bool windowed;
|
||
|
WW3D::Get_Device_Resolution(w,h,bits,windowed);
|
||
|
tmp.Format("Display mode: %d * %d, %d bits %s\r\n", w,h,bits,windowed ? "Windowed" : "Fullscreen");
|
||
|
str+=tmp;
|
||
|
|
||
|
str+="\r\n";
|
||
|
|
||
|
const char *VALUE_NAME_SOUND_DEVICE_NAME = "device name";
|
||
|
RegistryClass registry_sound( APPLICATION_SUB_KEY_NAME_SOUND );
|
||
|
if ( registry_sound.Is_Valid() ) {
|
||
|
char temp_buffer[256] = { 0 };
|
||
|
registry.Get_String (VALUE_NAME_SOUND_DEVICE_NAME, temp_buffer, sizeof (temp_buffer));
|
||
|
tmp.Format("Sound device: %s\r\n",temp_buffer);
|
||
|
str+=tmp;
|
||
|
}
|
||
|
|
||
|
WWAudioClass* audio=WWAudioClass::Get_Instance();
|
||
|
if (audio) {
|
||
|
tmp.Format("Sound effects: %s\r\n",audio->Are_Sound_Effects_On() ? "Enabled" : "Disabled");
|
||
|
str+=tmp;
|
||
|
tmp.Format("Sound effects volume: %2.2f\r\n",audio->Get_Sound_Effects_Volume());
|
||
|
str+=tmp;
|
||
|
tmp.Format("Music: %s\r\n",audio->Is_Music_On() ? "Enabled" : "Disabled");
|
||
|
str+=tmp;
|
||
|
tmp.Format("Music volume: %2.2f\r\n",audio->Get_Music_Volume());
|
||
|
str+=tmp;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Get_Compact_Detail_String(StringClass& str)
|
||
|
{
|
||
|
str="";
|
||
|
RegistryClass registry (APPLICATION_SUB_KEY_NAME_SYSTEM_SETTINGS);
|
||
|
if (registry.Is_Valid ()) {
|
||
|
|
||
|
//
|
||
|
// Read the values from the registry
|
||
|
//
|
||
|
int dynamic_lod = registry.Get_Int (VALUE_NAME_DYN_LOD, 3000);
|
||
|
int static_lod = registry.Get_Int (VALUE_NAME_STATIC_LOD, 3000);
|
||
|
|
||
|
int dynamic_shadows = registry.Get_Int (VALUE_NAME_DYN_SHADOWS, 1);
|
||
|
int static_shadows = registry.Get_Int (VALUE_NAME_STATIC_SHADOWS, 1);
|
||
|
|
||
|
int texture_filter = registry.Get_Int (VALUE_NAME_TEXTURE_FILTER_MODE, TextureClass::TEXTURE_FILTER_BILINEAR);
|
||
|
int prelit_mode = registry.Get_Int (VALUE_NAME_PRELIT_MODE, WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE);
|
||
|
int shadow_mode = registry.Get_Int (VALUE_NAME_SHADOW_MODE, PhysicsSceneClass::SHADOW_MODE_BLOBS_PLUS);
|
||
|
int texture_red = registry.Get_Int (VALUE_NAME_TEXTURE_RES, 0);
|
||
|
int surface_effect = registry.Get_Int (VALUE_NAME_SURFACE_EFFECT, 1);
|
||
|
int particle_detail = registry.Get_Int (VALUE_NAME_PARTICLE_DETAIL, 1);
|
||
|
|
||
|
StringClass tmp;
|
||
|
tmp.Format("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t",dynamic_lod,static_lod,shadow_mode,dynamic_shadows,static_shadows,prelit_mode,texture_red,surface_effect,particle_detail,texture_filter);
|
||
|
str+=tmp;
|
||
|
|
||
|
tmp.Format("%d\t",1);//WW3D::Get_Texture_Compression_Mode());
|
||
|
str+=tmp;
|
||
|
|
||
|
int w;
|
||
|
int h;
|
||
|
int bits;
|
||
|
bool windowed;
|
||
|
WW3D::Get_Device_Resolution(w,h,bits,windowed);
|
||
|
tmp.Format("%d\t%d\t%d\t%d\t",w,h,bits,windowed);
|
||
|
str+=tmp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static class SysInfoCopyThreadClass : public ThreadClass
|
||
|
{
|
||
|
public:
|
||
|
StringClass String;
|
||
|
StringClass Filename;
|
||
|
|
||
|
SysInfoCopyThreadClass()
|
||
|
:
|
||
|
ThreadClass("SysInfoCopyThread", &Exception_Handler) {}
|
||
|
|
||
|
void Thread_Function()
|
||
|
{
|
||
|
DWORD written;
|
||
|
HANDLE file = CreateFile(Filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
||
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
if (INVALID_HANDLE_VALUE != file) {
|
||
|
WriteFile(file, String, strlen(String), &written, NULL);
|
||
|
CloseHandle(file);
|
||
|
}
|
||
|
}
|
||
|
} SysInfoCopyThread;
|
||
|
|
||
|
// For debug purposes, log system information to \\Mordane\marketin\transfer\users\Jani\SYSINFO
|
||
|
static void Log_System_Information()
|
||
|
{
|
||
|
if (!DX8Wrapper::Is_Initted()) {
|
||
|
return;
|
||
|
}
|
||
|
if (DX8Wrapper::Get_Current_Caps() == NULL) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
char name[MAX_COMPUTERNAME_LENGTH + 1];
|
||
|
DWORD size = sizeof(name);
|
||
|
::GetComputerName(name, &size);
|
||
|
|
||
|
char user[UNLEN+1];
|
||
|
DWORD userlen=sizeof(user);
|
||
|
::GetUserName(user, &userlen);
|
||
|
|
||
|
StringClass string; // This will be a long string so don't allocate locally!
|
||
|
string.Format("Computer name: %s\r\nUser name: %s\r\n\r\n",name,user);
|
||
|
string+=CPUDetectClass::Get_Processor_Log();
|
||
|
if (DX8Wrapper::Get_Current_Caps()) {
|
||
|
string+=DX8Wrapper::Get_Current_Caps()->Get_Log();
|
||
|
}
|
||
|
string+="\r\n";
|
||
|
string+="Compact tab-delimited version:\r\n";
|
||
|
StringClass tmp; // This will be long so no local alloc needed
|
||
|
|
||
|
string+=CPUDetectClass::Get_Compact_Log();
|
||
|
if (DX8Wrapper::Get_Current_Caps()) {
|
||
|
string+=DX8Wrapper::Get_Current_Caps()->Get_Compact_Log();
|
||
|
}
|
||
|
Get_Compact_Detail_String(tmp);
|
||
|
string+=tmp;
|
||
|
SystemInfoLog::Get_Compact_Log(tmp);
|
||
|
string+=tmp;
|
||
|
string+="\r\n";
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
Get_Detail_String(tmp);
|
||
|
string+=tmp;
|
||
|
string+="\r\n";
|
||
|
|
||
|
SystemInfoLog::Get_Log(tmp);
|
||
|
string+=tmp;
|
||
|
|
||
|
// Write log to network folder
|
||
|
DWORD written;
|
||
|
HANDLE file;
|
||
|
|
||
|
#ifdef WWDEBUG
|
||
|
RegistryClass registry( APPLICATION_SUB_KEY_NAME_DEBUG );
|
||
|
if ( registry.Is_Valid() ) {
|
||
|
int disable=registry.Get_Int( SYSTEM_INFO_LOG_DISABLE );
|
||
|
if (!disable) {
|
||
|
if (!SysInfoCopyThread.Is_Running()) {
|
||
|
StringClass filename(0,true);
|
||
|
// filename="\\\\havoc\\rock\\projects\\renegade\\logs\\";
|
||
|
filename="\\\\tanya\\game\\Projects\\Renegade\\_sysinfo_logs\\";
|
||
|
tmp.Format("%d_%d_",DX8Wrapper::Get_Current_Caps()->Get_Vendor(),DX8Wrapper::Get_Current_Caps()->Get_Device());
|
||
|
filename+=tmp;
|
||
|
filename+=name;
|
||
|
filename+=".txt";
|
||
|
|
||
|
SysInfoCopyThread.String=string;
|
||
|
SysInfoCopyThread.Filename=filename;
|
||
|
SysInfoCopyThread.Execute();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// Write log to local work folder
|
||
|
file = CreateFile("sysinfo.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
||
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
if (INVALID_HANDLE_VALUE != file) {
|
||
|
WriteFile(file, string, strlen(string), &written, NULL);
|
||
|
CloseHandle(file);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
void Debug_Refs(void);
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
void Game_Shutdown(void)
|
||
|
{
|
||
|
Log_System_Information();
|
||
|
|
||
|
BINKMovie::Shutdown();
|
||
|
|
||
|
CampaignManager::Shutdown();
|
||
|
|
||
|
SystemSettings::Shutdown();
|
||
|
CombatManager::Shutdown();
|
||
|
|
||
|
//Analyze_Soldier_Bandwidth();
|
||
|
|
||
|
cNetwork::Onetime_Shutdown();
|
||
|
|
||
|
cServerFps::Destroy_Instance();
|
||
|
|
||
|
cPlayerManager::Onetime_Shutdown();
|
||
|
cTeamManager::Onetime_Shutdown();
|
||
|
cGameData::Onetime_Shutdown();
|
||
|
cBandwidthGraph::Onetime_Shutdown();
|
||
|
|
||
|
DebugManager::Set_Display_Handler( NULL );
|
||
|
|
||
|
GameModeManager::Destroy_All();
|
||
|
EncyclopediaMgrClass::Shutdown();
|
||
|
RenegadeDialogMgrClass::Shutdown();
|
||
|
|
||
|
// Free the sound library
|
||
|
if (WWAudioClass::Get_Instance () != NULL) {
|
||
|
//WWAudioClass::Get_Instance ()->Shutdown ();
|
||
|
delete WWAudioClass::Get_Instance ();
|
||
|
}
|
||
|
|
||
|
//GameSettings::Shutdown();
|
||
|
|
||
|
SkinPackageMgrClass::Shutdown ();
|
||
|
ModPackageMgrClass::Shutdown ();
|
||
|
TranslateDBClass::Shutdown();
|
||
|
|
||
|
//
|
||
|
// Shutdown the input control system
|
||
|
//
|
||
|
InputConfigMgrClass::Shutdown();
|
||
|
Input::Save_Registry( APPLICATION_SUB_KEY_NAME_CONTROLS );
|
||
|
Input::Shutdown();
|
||
|
|
||
|
DiagLogClass::Shutdown();
|
||
|
|
||
|
// CommandoAssetManager::Shutdown();
|
||
|
WW3D::_Invalidate_Textures();
|
||
|
WWASSERT( WW3DAssetManager::Get_Instance() );
|
||
|
WW3DAssetManager::Delete_This();
|
||
|
// if ( WW3DAssetManager::Get_Instance() ) {
|
||
|
// delete WW3DAssetManager::Get_Instance();
|
||
|
// }
|
||
|
|
||
|
cDiagnostics::Close();
|
||
|
//cHelpText::Close();
|
||
|
|
||
|
PhysicsSceneClass * scene = PhysicsSceneClass::Get_Instance();
|
||
|
scene->Set_Max_Simultaneous_Shadows(0);
|
||
|
|
||
|
PathMgrClass::Shutdown();
|
||
|
WWMath::Shutdown();
|
||
|
WWSaveLoad::Shutdown();
|
||
|
WW3D::Shutdown();
|
||
|
WWPhys::Shutdown();
|
||
|
|
||
|
// WW3DAssetManager::Get_Instance()->Free_Assets();
|
||
|
Debug_Refs();
|
||
|
|
||
|
DebugManager::Save_Registry_Settings( APPLICATION_SUB_KEY_NAME_DEBUG );
|
||
|
DebugManager::Shutdown();
|
||
|
|
||
|
WSA_CHECK(WSACleanup());
|
||
|
|
||
|
/*
|
||
|
** Remove any old file factories still lying around.
|
||
|
*/
|
||
|
if (FileFactoryListClass::Get_Instance() != NULL) {
|
||
|
FileFactoryListClass::Get_Instance()->Remove_FileFactory(&RenegadeBaseFileFactory);
|
||
|
}
|
||
|
while (FileFactoryListClass::Get_Instance() != NULL) {
|
||
|
FileFactoryClass * factory = FileFactoryListClass::Get_Instance()->Remove_FileFactory();
|
||
|
if (factory != NULL) {
|
||
|
WWDEBUG_SAY(("Removing pesky old file factory\n"));
|
||
|
delete factory;
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
RegistryClass registry( APPLICATION_SUB_KEY_NAME_DEBUG );
|
||
|
if ( registry.Is_Valid() ) {
|
||
|
registry.Set_Int( VALUE_NAME_APPLICATION_CRASH_VERSION, 0 );
|
||
|
}
|
||
|
|
||
|
#ifdef FREEDEDICATEDSERVER
|
||
|
Copy_Logs(DebugManager::Get_Version_Number());
|
||
|
#endif //FREEDEDICATEDSERVER
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
void Debug_Refs(void)
|
||
|
{
|
||
|
#ifndef NDEBUG
|
||
|
// Debug_Say(("Detecting Active Refs...\r\n"));
|
||
|
RefCountNodeClass * first = RefCountClass::ActiveRefList.First();
|
||
|
RefCountNodeClass * node = first;
|
||
|
while (node->Is_Valid())
|
||
|
{
|
||
|
RefCountClass * obj = node->Get();
|
||
|
ActiveRefStruct * ref = &(obj->ActiveRefInfo);
|
||
|
|
||
|
bool display = true;
|
||
|
int count = 0;
|
||
|
RefCountNodeClass * search = first;
|
||
|
while (search->Is_Valid()) {
|
||
|
|
||
|
if (search == node) { // if this is not the first one
|
||
|
if (count != 0) {
|
||
|
display = false;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RefCountClass * search_obj = search->Get();
|
||
|
ActiveRefStruct * search_ref = &(search_obj->ActiveRefInfo);
|
||
|
|
||
|
if ( ref->File && search_ref->File &&
|
||
|
!strcmp(search_ref->File, ref->File) &&
|
||
|
(search_ref->Line == ref->Line) ) {
|
||
|
count++;
|
||
|
} else if ( (ref->File == NULL) && (search_ref->File == NULL) ) {
|
||
|
count++;
|
||
|
}
|
||
|
|
||
|
search = search->Next();
|
||
|
}
|
||
|
|
||
|
if ( display ) {
|
||
|
Debug_Say(( "%d Active Ref: %s %d %p\n", count, ref->File,ref->Line,obj));
|
||
|
|
||
|
static int num_printed = 0;
|
||
|
if (++num_printed > 20) {
|
||
|
Debug_Say(( "And Many More......\n"));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
node = node->Next();
|
||
|
}
|
||
|
// Debug_Say(("Done.\r\n"));
|
||
|
#endif
|
||
|
}
|