diff --git a/Doxyfile b/Doxyfile
index 87bd77fc..78cfcbab 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -55,7 +55,8 @@ EXCLUDE = src/3rd-party \
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
-PREDEFINED = KGE_API=
+PREDEFINED = KGE_API= \
+ KGE_DISABLE_DOXYGEN=
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the
diff --git a/projects/3rd-party/Box2D/libBox2D.vcxproj b/projects/3rd-party/Box2D/libBox2D.vcxproj
index d4adf92f..7e2bab7c 100644
--- a/projects/3rd-party/Box2D/libBox2D.vcxproj
+++ b/projects/3rd-party/Box2D/libBox2D.vcxproj
@@ -185,4 +185,4 @@
-
\ No newline at end of file
+
diff --git a/projects/3rd-party/StackWalker/libStackWalker.vcxproj b/projects/3rd-party/StackWalker/libStackWalker.vcxproj
deleted file mode 100644
index 8907d076..00000000
--- a/projects/3rd-party/StackWalker/libStackWalker.vcxproj
+++ /dev/null
@@ -1,97 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Debug
- Win32
-
-
- Release
- Win32
-
-
-
- {3A3948DC-9865-46B3-B7B9-7E5572704ED2}
- libStackWalker
-
-
-
- StaticLibrary
- true
- Unicode
- $(DefaultPlatformToolset)
-
-
- StaticLibrary
- false
- false
- Unicode
- $(DefaultPlatformToolset)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(SolutionDir)\output\$(PlatformToolset)\$(Platform)\$(Configuration)\
- $(SolutionDir)\build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\
- true
-
-
- $(SolutionDir)\output\$(PlatformToolset)\$(Platform)\$(Configuration)\
- $(SolutionDir)\build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\
- true
-
-
-
- Level3
- Disabled
- true
- None
- true
- ../../../src/3rd-party;
- false
-
-
- Windows
- true
-
-
-
-
- Level3
- MaxSpeed
- true
- true
- false
- true
- None
- true
- ../../../src/3rd-party;
- false
-
-
- Windows
- false
- true
- true
-
-
-
-
-
-
\ No newline at end of file
diff --git a/projects/3rd-party/StackWalker/libStackWalker.vcxproj.filters b/projects/3rd-party/StackWalker/libStackWalker.vcxproj.filters
deleted file mode 100644
index 08a3c777..00000000
--- a/projects/3rd-party/StackWalker/libStackWalker.vcxproj.filters
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/projects/3rd-party/curl/libcurl.vcxproj b/projects/3rd-party/curl/libcurl.vcxproj
index 9a4c7664..4fa3e9d3 100644
--- a/projects/3rd-party/curl/libcurl.vcxproj
+++ b/projects/3rd-party/curl/libcurl.vcxproj
@@ -102,4 +102,4 @@
-
\ No newline at end of file
+
diff --git a/projects/3rd-party/imgui/libimgui.vcxproj b/projects/3rd-party/imgui/libimgui.vcxproj
index 0912e006..10ff944f 100644
--- a/projects/3rd-party/imgui/libimgui.vcxproj
+++ b/projects/3rd-party/imgui/libimgui.vcxproj
@@ -102,4 +102,4 @@
-
\ No newline at end of file
+
diff --git a/projects/3rd-party/tinyxml2/libtinyxml2.vcxproj b/projects/3rd-party/tinyxml2/libtinyxml2.vcxproj
index d6ba3b24..8d2e1039 100644
--- a/projects/3rd-party/tinyxml2/libtinyxml2.vcxproj
+++ b/projects/3rd-party/tinyxml2/libtinyxml2.vcxproj
@@ -94,4 +94,4 @@
-
\ No newline at end of file
+
diff --git a/projects/Kiwano.sln b/projects/Kiwano.sln
index 3cf1ce1f..2899bd53 100644
--- a/projects/Kiwano.sln
+++ b/projects/Kiwano.sln
@@ -14,8 +14,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kiwano-physics", "kiwano-ph
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3rd-party", "3rd-party", "{2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libStackWalker", "3rd-party\StackWalker\libStackWalker.vcxproj", "{3A3948DC-9865-46B3-B7B9-7E5572704ED2}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtinyxml2", "3rd-party\tinyxml2\libtinyxml2.vcxproj", "{AB47E875-85E5-4105-A71E-88930EAAB910}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libimgui", "3rd-party\imgui\libimgui.vcxproj", "{7FA1E56D-62AC-47D1-97D1-40B302724198}"
@@ -47,10 +45,10 @@ Global
{A7062ED8-8910-48A5-A3BC-C1612672571F}.Debug|Win32.Build.0 = Debug|Win32
{A7062ED8-8910-48A5-A3BC-C1612672571F}.Release|Win32.ActiveCfg = Release|Win32
{A7062ED8-8910-48A5-A3BC-C1612672571F}.Release|Win32.Build.0 = Release|Win32
- {3A3948DC-9865-46B3-B7B9-7E5572704ED2}.Debug|Win32.ActiveCfg = Debug|Win32
- {3A3948DC-9865-46B3-B7B9-7E5572704ED2}.Debug|Win32.Build.0 = Debug|Win32
- {3A3948DC-9865-46B3-B7B9-7E5572704ED2}.Release|Win32.ActiveCfg = Release|Win32
- {3A3948DC-9865-46B3-B7B9-7E5572704ED2}.Release|Win32.Build.0 = Release|Win32
+ {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Debug|Win32.Build.0 = Debug|Win32
+ {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Release|Win32.ActiveCfg = Release|Win32
+ {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Release|Win32.Build.0 = Release|Win32
{AB47E875-85E5-4105-A71E-88930EAAB910}.Debug|Win32.ActiveCfg = Debug|Win32
{AB47E875-85E5-4105-A71E-88930EAAB910}.Debug|Win32.Build.0 = Debug|Win32
{AB47E875-85E5-4105-A71E-88930EAAB910}.Release|Win32.ActiveCfg = Release|Win32
@@ -67,16 +65,11 @@ Global
{0CBA9295-F14D-4966-A7C4-1DD68158176C}.Debug|Win32.Build.0 = Debug|Win32
{0CBA9295-F14D-4966-A7C4-1DD68158176C}.Release|Win32.ActiveCfg = Release|Win32
{0CBA9295-F14D-4966-A7C4-1DD68158176C}.Release|Win32.Build.0 = Release|Win32
- {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Debug|Win32.ActiveCfg = Debug|Win32
- {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Debug|Win32.Build.0 = Debug|Win32
- {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Release|Win32.ActiveCfg = Release|Win32
- {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
- {3A3948DC-9865-46B3-B7B9-7E5572704ED2} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}
{AB47E875-85E5-4105-A71E-88930EAAB910} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}
{7FA1E56D-62AC-47D1-97D1-40B302724198} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}
{A9ABACC7-75A1-46BA-8E48-4105346D9719} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}
diff --git a/projects/kiwano-audio/kiwano-audio.vcxproj b/projects/kiwano-audio/kiwano-audio.vcxproj
index c593786f..7836bc77 100644
--- a/projects/kiwano-audio/kiwano-audio.vcxproj
+++ b/projects/kiwano-audio/kiwano-audio.vcxproj
@@ -39,7 +39,7 @@
StaticLibrary
false
- false
+ true
Unicode
$(DefaultPlatformToolset)
@@ -108,4 +108,4 @@
-
\ No newline at end of file
+
diff --git a/projects/kiwano-imgui/kiwano-imgui.vcxproj b/projects/kiwano-imgui/kiwano-imgui.vcxproj
index faecc0d6..55833de5 100644
--- a/projects/kiwano-imgui/kiwano-imgui.vcxproj
+++ b/projects/kiwano-imgui/kiwano-imgui.vcxproj
@@ -38,7 +38,7 @@
StaticLibrary
false
- false
+ true
Unicode
$(DefaultPlatformToolset)
@@ -110,4 +110,4 @@
-
\ No newline at end of file
+
diff --git a/projects/kiwano-network/kiwano-network.vcxproj b/projects/kiwano-network/kiwano-network.vcxproj
index 4192e881..6883d0be 100644
--- a/projects/kiwano-network/kiwano-network.vcxproj
+++ b/projects/kiwano-network/kiwano-network.vcxproj
@@ -34,7 +34,7 @@
StaticLibrary
false
- false
+ true
Unicode
$(DefaultPlatformToolset)
@@ -106,4 +106,4 @@
-
\ No newline at end of file
+
diff --git a/projects/kiwano-physics/kiwano-physics.vcxproj b/projects/kiwano-physics/kiwano-physics.vcxproj
index cc69700c..9fb99160 100644
--- a/projects/kiwano-physics/kiwano-physics.vcxproj
+++ b/projects/kiwano-physics/kiwano-physics.vcxproj
@@ -44,7 +44,7 @@
StaticLibrary
false
- false
+ true
Unicode
$(DefaultPlatformToolset)
@@ -116,4 +116,4 @@
-
\ No newline at end of file
+
diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj
index e83c8301..e7b30047 100644
--- a/projects/kiwano/kiwano.vcxproj
+++ b/projects/kiwano/kiwano.vcxproj
@@ -123,6 +123,7 @@
+
@@ -158,9 +159,6 @@
-
- {3a3948dc-9865-46b3-b7b9-7e5572704ed2}
-
{ab47e875-85e5-4105-a71e-88930eaab910}
@@ -179,7 +177,7 @@
StaticLibrary
false
- false
+ true
Unicode
$(DefaultPlatformToolset)
@@ -241,4 +239,4 @@
-
\ No newline at end of file
+
diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters
index 504b6bf1..20d6b9e6 100644
--- a/projects/kiwano/kiwano.vcxproj.filters
+++ b/projects/kiwano/kiwano.vcxproj.filters
@@ -458,5 +458,8 @@
platform\win32
+
+ platform\win32
+
\ No newline at end of file
diff --git a/scripts/appveyor/clear_project_configuration.ps1 b/scripts/appveyor/clear_project_configuration.ps1
index 05b9fba9..185ad6bf 100644
--- a/scripts/appveyor/clear_project_configuration.ps1
+++ b/scripts/appveyor/clear_project_configuration.ps1
@@ -3,14 +3,19 @@ function Set-FileConfiguration {
[string]$filePath
)
- $replace = "(EditAndContinue|ProgramDatabase)"
- $replaceTo = "None"
+ $debugInfoReplace = "(EditAndContinue|ProgramDatabase)"
+ $debugInfoReplaceTo = "None"
+
+ $optimizationReplace = "true"
+ $optimizationReplaceTo = "false"
# Create a copy of .vcxproj file
Copy-Item -Path $filePath -Destination ($filePath + '.template')
# Overlay some configurations
- Get-Content ($filePath + '.template') -Encoding UTF8 | ForEach-Object { $_ -replace $replace, $replaceTo } | Out-File $filePath -Encoding UTF8
+ Get-Content ($filePath + '.template') -Encoding UTF8 | ForEach-Object {
+ ( $_ -replace $debugInfoReplace, $debugInfoReplaceTo ) -replace $optimizationReplace, $optimizationReplaceTo
+ } | Out-File $filePath -Encoding UTF8
# Delete the copy file
Remove-Item -Path ($filePath + '.template')
@@ -24,3 +29,12 @@ Get-ChildItem -Path 'projects\' -Directory | ForEach-Object {
Set-FileConfiguration ($dirPath + '\' + $_)
}
}
+
+Get-ChildItem -Path 'projects\3rd-party' -Directory | ForEach-Object {
+ $dirPath = "projects\3rd-party\$($_)"
+
+ # Search all vcxproj files
+ Get-ChildItem -Path $dirPath *.vcxproj -File | ForEach-Object {
+ Set-FileConfiguration ($dirPath + '\' + $_)
+ }
+}
diff --git a/src/3rd-party/StackWalker/StackWalker.cpp b/src/3rd-party/StackWalker/StackWalker.cpp
deleted file mode 100644
index decb9d4a..00000000
--- a/src/3rd-party/StackWalker/StackWalker.cpp
+++ /dev/null
@@ -1,1223 +0,0 @@
-/**********************************************************************
- *
- * StackWalker.cpp
- *
- *
- * History:
- * 2005-07-27 v1 - First public release on http://www.codeproject.com/
- * http://www.codeproject.com/threads/StackWalker.asp
- * 2005-07-28 v2 - Changed the params of the constructor and ShowCallstack
- * (to simplify the usage)
- * 2005-08-01 v3 - Changed to use 'CONTEXT_FULL' instead of CONTEXT_ALL
- * (should also be enough)
- * - Changed to compile correctly with the PSDK of VC7.0
- * (GetFileVersionInfoSizeA and GetFileVersionInfoA is wrongly defined:
- * it uses LPSTR instead of LPCSTR as first paremeter)
- * - Added declarations to support VC5/6 without using 'dbghelp.h'
- * - Added a 'pUserData' member to the ShowCallstack function and the
- * PReadProcessMemoryRoutine declaration (to pass some user-defined data,
- * which can be used in the readMemoryFunction-callback)
- * 2005-08-02 v4 - OnSymInit now also outputs the OS-Version by default
- * - Added example for doing an exception-callstack-walking in main.cpp
- * (thanks to owillebo: http://www.codeproject.com/script/profile/whos_who.asp?id=536268)
- * 2005-08-05 v5 - Removed most Lint (http://www.gimpel.com/) errors... thanks to Okko Willeboordse!
- *
- **********************************************************************/
-#include
-#include
-#include
-#pragma comment(lib, "version.lib") // for "VerQueryValue"
-
-#include "StackWalker.h"
-
-
-// If VC7 and later, then use the shipped 'dbghelp.h'-file
-#if _MSC_VER >= 1300
-#pragma warning(push)
-#pragma warning(disable : 4091) // ignore warning in
-#include
-#pragma warning(pop)
-#else
-// inline the important dbghelp.h-declarations...
-typedef enum {
- SymNone = 0,
- SymCoff,
- SymCv,
- SymPdb,
- SymExport,
- SymDeferred,
- SymSym,
- SymDia,
- SymVirtual,
- NumSymTypes
-} SYM_TYPE;
-typedef struct _IMAGEHLP_LINE64 {
- DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_LINE64)
- PVOID Key; // internal
- DWORD LineNumber; // line number in file
- PCHAR FileName; // full filename
- DWORD64 Address; // first instruction of line
-} IMAGEHLP_LINE64, *PIMAGEHLP_LINE64;
-typedef struct _IMAGEHLP_MODULE64 {
- DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64)
- DWORD64 BaseOfImage; // base load address of module
- DWORD ImageSize; // virtual size of the loaded module
- DWORD TimeDateStamp; // date/time stamp from pe header
- DWORD CheckSum; // checksum from the pe header
- DWORD NumSyms; // number of symbols in the symbol table
- SYM_TYPE SymType; // type of symbols loaded
- CHAR ModuleName[32]; // module name
- CHAR ImageName[256]; // image name
- CHAR LoadedImageName[256]; // symbol file name
-} IMAGEHLP_MODULE64, *PIMAGEHLP_MODULE64;
-typedef struct _IMAGEHLP_SYMBOL64 {
- DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_SYMBOL64)
- DWORD64 Address; // virtual address including dll base address
- DWORD Size; // estimated size of symbol, can be zero
- DWORD Flags; // info about the symbols, see the SYMF defines
- DWORD MaxNameLength; // maximum size of symbol name in 'Name'
- CHAR Name[1]; // symbol name (null terminated string)
-} IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64;
-typedef enum {
- AddrMode1616,
- AddrMode1632,
- AddrModeReal,
- AddrModeFlat
-} ADDRESS_MODE;
-typedef struct _tagADDRESS64 {
- DWORD64 Offset;
- WORD Segment;
- ADDRESS_MODE Mode;
-} ADDRESS64, *LPADDRESS64;
-typedef struct _KDHELP64 {
- DWORD64 Thread;
- DWORD ThCallbackStack;
- DWORD ThCallbackBStore;
- DWORD NextCallback;
- DWORD FramePointer;
- DWORD64 KiCallUserMode;
- DWORD64 KeUserCallbackDispatcher;
- DWORD64 SystemRangeStart;
- DWORD64 Reserved[8];
-} KDHELP64, *PKDHELP64;
-typedef struct _tagSTACKFRAME64 {
- ADDRESS64 AddrPC; // program counter
- ADDRESS64 AddrReturn; // return address
- ADDRESS64 AddrFrame; // frame pointer
- ADDRESS64 AddrStack; // stack pointer
- ADDRESS64 AddrBStore; // backing store pointer
- PVOID FuncTableEntry; // pointer to pdata/fpo or NULL
- DWORD64 Params[4]; // possible arguments to the function
- BOOL Far; // WOW far call
- BOOL Virtual; // is this a virtual frame?
- DWORD64 Reserved[3];
- KDHELP64 KdHelp;
-} STACKFRAME64, *LPSTACKFRAME64;
-typedef
-BOOL
-(__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(
- HANDLE hProcess,
- DWORD64 qwBaseAddress,
- PVOID lpBuffer,
- DWORD nSize,
- LPDWORD lpNumberOfBytesRead
- );
-typedef
-PVOID
-(__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)(
- HANDLE hProcess,
- DWORD64 AddrBase
- );
-typedef
-DWORD64
-(__stdcall *PGET_MODULE_BASE_ROUTINE64)(
- HANDLE hProcess,
- DWORD64 Address
- );
-typedef
-DWORD64
-(__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(
- HANDLE hProcess,
- HANDLE hThread,
- LPADDRESS64 lpaddr
- );
-#define SYMOPT_CASE_INSENSITIVE 0x00000001
-#define SYMOPT_UNDNAME 0x00000002
-#define SYMOPT_DEFERRED_LOADS 0x00000004
-#define SYMOPT_NO_CPP 0x00000008
-#define SYMOPT_LOAD_LINES 0x00000010
-#define SYMOPT_OMAP_FIND_NEAREST 0x00000020
-#define SYMOPT_LOAD_ANYTHING 0x00000040
-#define SYMOPT_IGNORE_CVREC 0x00000080
-#define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100
-#define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200
-#define SYMOPT_EXACT_SYMBOLS 0x00000400
-#define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800
-#define SYMOPT_IGNORE_NT_SYMPATH 0x00001000
-#define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000
-#define SYMOPT_PUBLICS_ONLY 0x00004000
-#define SYMOPT_NO_PUBLICS 0x00008000
-#define SYMOPT_AUTO_PUBLICS 0x00010000
-#define SYMOPT_NO_IMAGE_SEARCH 0x00020000
-#define SYMOPT_SECURE 0x00040000
-#define SYMOPT_DEBUG 0x80000000
-#define UNDNAME_COMPLETE (0x0000) // Enable full undecoration
-#define UNDNAME_NAME_ONLY (0x1000) // Crack only the name for primary declaration;
-#endif // _MSC_VER < 1300
-
-// Some missing defines (for VC5/6):
-#ifndef INVALID_FILE_ATTRIBUTES
-#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
-#endif
-
-
-// secure-CRT_functions are only available starting with VC8
-#if _MSC_VER < 1400
-#define strcpy_s strcpy
-#define strcat_s(dst, len, src) strcat(dst, src)
-#define _snprintf_s _snprintf
-#define _tcscat_s _tcscat
-#endif
-
-// Normally it should be enough to use 'CONTEXT_FULL' (better would be 'CONTEXT_ALL')
-#define USED_CONTEXT_FLAGS CONTEXT_FULL
-
-
-class StackWalkerInternal
-{
-public:
- StackWalkerInternal(StackWalker *parent, HANDLE hProcess)
- {
- m_parent = parent;
- m_hDbhHelp = NULL;
- pSC = NULL;
- m_hProcess = hProcess;
- m_szSymPath = NULL;
- pSFTA = NULL;
- pSGLFA = NULL;
- pSGMB = NULL;
- pSGMI = NULL;
- pSGO = NULL;
- pSGSFA = NULL;
- pSI = NULL;
- pSLM = NULL;
- pSSO = NULL;
- pSW = NULL;
- pUDSN = NULL;
- pSGSP = NULL;
- }
- ~StackWalkerInternal()
- {
- if (pSC != NULL)
- pSC(m_hProcess); // SymCleanup
- if (m_hDbhHelp != NULL)
- FreeLibrary(m_hDbhHelp);
- m_hDbhHelp = NULL;
- m_parent = NULL;
- if(m_szSymPath != NULL)
- free(m_szSymPath);
- m_szSymPath = NULL;
- }
- BOOL Init(LPCSTR szSymPath)
- {
- if (m_parent == NULL)
- return FALSE;
- // Dynamically load the Entry-Points for dbghelp.dll:
- // First try to load the newsest one from
- TCHAR szTemp[4096];
- // But before wqe do this, we first check if the ".local" file exists
- if (GetModuleFileName(NULL, szTemp, 4096) > 0)
- {
- _tcscat_s(szTemp, _T(".local"));
- if (GetFileAttributes(szTemp) == INVALID_FILE_ATTRIBUTES)
- {
- // ".local" file does not exist, so we can try to load the dbghelp.dll from the "Debugging Tools for Windows"
- if (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, 4096) > 0)
- {
- _tcscat_s(szTemp, _T("\\Debugging Tools for Windows\\dbghelp.dll"));
- // now check if the file exists:
- if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES)
- {
- m_hDbhHelp = LoadLibrary(szTemp);
- }
- }
- // Still not found? Then try to load the 64-Bit version:
- if ( (m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, 4096) > 0) )
- {
- _tcscat_s(szTemp, _T("\\Debugging Tools for Windows 64-Bit\\dbghelp.dll"));
- if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES)
- {
- m_hDbhHelp = LoadLibrary(szTemp);
- }
- }
- }
- }
- if (m_hDbhHelp == NULL) // if not already loaded, try to load a default-one
- m_hDbhHelp = LoadLibrary( _T("dbghelp.dll") );
- if (m_hDbhHelp == NULL)
- return FALSE;
- pSI = (tSI) GetProcAddress(m_hDbhHelp, "SymInitialize" );
- pSC = (tSC) GetProcAddress(m_hDbhHelp, "SymCleanup" );
-
- pSW = (tSW) GetProcAddress(m_hDbhHelp, "StackWalk64" );
- pSGO = (tSGO) GetProcAddress(m_hDbhHelp, "SymGetOptions" );
- pSSO = (tSSO) GetProcAddress(m_hDbhHelp, "SymSetOptions" );
-
- pSFTA = (tSFTA) GetProcAddress(m_hDbhHelp, "SymFunctionTableAccess64" );
- pSGLFA = (tSGLFA) GetProcAddress(m_hDbhHelp, "SymGetLineFromAddr64" );
- pSGMB = (tSGMB) GetProcAddress(m_hDbhHelp, "SymGetModuleBase64" );
- pSGMI = (tSGMI) GetProcAddress(m_hDbhHelp, "SymGetModuleInfo64" );
- //pSGMI_V3 = (tSGMI_V3) GetProcAddress(m_hDbhHelp, "SymGetModuleInfo64" );
- pSGSFA = (tSGSFA) GetProcAddress(m_hDbhHelp, "SymGetSymFromAddr64" );
- pUDSN = (tUDSN) GetProcAddress(m_hDbhHelp, "UnDecorateSymbolName" );
- pSLM = (tSLM) GetProcAddress(m_hDbhHelp, "SymLoadModule64" );
- pSGSP =(tSGSP) GetProcAddress(m_hDbhHelp, "SymGetSearchPath" );
-
- if ( pSC == NULL || pSFTA == NULL || pSGMB == NULL || pSGMI == NULL ||
- pSGO == NULL || pSGSFA == NULL || pSI == NULL || pSSO == NULL ||
- pSW == NULL || pUDSN == NULL || pSLM == NULL )
- {
- FreeLibrary(m_hDbhHelp);
- m_hDbhHelp = NULL;
- pSC = NULL;
- return FALSE;
- }
-
- // SymInitialize
- if (szSymPath != NULL)
- m_szSymPath = _strdup(szSymPath);
- if (this->pSI(m_hProcess, m_szSymPath, FALSE) == FALSE)
- this->m_parent->OnDbgHelpErr("SymInitialize", GetLastError(), 0);
-
- DWORD symOptions = this->pSGO(); // SymGetOptions
- symOptions |= SYMOPT_LOAD_LINES;
- symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS;
- //symOptions |= SYMOPT_NO_PROMPTS;
- // SymSetOptions
- symOptions = this->pSSO(symOptions);
-
- /*char buf[StackWalker::STACKWALK_MAX_NAMELEN] = {0};
- if (this->pSGSP != NULL)
- {
- if (this->pSGSP(m_hProcess, buf, StackWalker::STACKWALK_MAX_NAMELEN) == FALSE)
- this->m_parent->OnDbgHelpErr("SymGetSearchPath", GetLastError(), 0);
- }
- char szUserName[1024] = {0};
- DWORD dwSize = 1024;
- GetUserNameA(szUserName, &dwSize);
- this->m_parent->OnSymInit(buf, symOptions, szUserName);*/
-
- return TRUE;
- }
-
- StackWalker *m_parent;
-
- HMODULE m_hDbhHelp;
- HANDLE m_hProcess;
- LPSTR m_szSymPath;
-
-/*typedef struct IMAGEHLP_MODULE64_V3 {
- DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64)
- DWORD64 BaseOfImage; // base load address of module
- DWORD ImageSize; // virtual size of the loaded module
- DWORD TimeDateStamp; // date/time stamp from pe header
- DWORD CheckSum; // checksum from the pe header
- DWORD NumSyms; // number of symbols in the symbol table
- SYM_TYPE SymType; // type of symbols loaded
- CHAR ModuleName[32]; // module name
- CHAR ImageName[256]; // image name
- // new elements: 07-Jun-2002
- CHAR LoadedImageName[256]; // symbol file name
- CHAR LoadedPdbName[256]; // pdb file name
- DWORD CVSig; // Signature of the CV record in the debug directories
- CHAR CVData[MAX_PATH * 3]; // Contents of the CV record
- DWORD PdbSig; // Signature of PDB
- GUID PdbSig70; // Signature of PDB (VC 7 and up)
- DWORD PdbAge; // DBI age of pdb
- BOOL PdbUnmatched; // loaded an unmatched pdb
- BOOL DbgUnmatched; // loaded an unmatched dbg
- BOOL LineNumbers; // we have line number information
- BOOL GlobalSymbols; // we have internal symbol information
- BOOL TypeInfo; // we have type information
- // new elements: 17-Dec-2003
- BOOL SourceIndexed; // pdb supports source server
- BOOL Publics; // contains public symbols
-};
-*/
-struct IMAGEHLP_MODULE64_V2 {
- DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64)
- DWORD64 BaseOfImage; // base load address of module
- DWORD ImageSize; // virtual size of the loaded module
- DWORD TimeDateStamp; // date/time stamp from pe header
- DWORD CheckSum; // checksum from the pe header
- DWORD NumSyms; // number of symbols in the symbol table
- SYM_TYPE SymType; // type of symbols loaded
- CHAR ModuleName[32]; // module name
- CHAR ImageName[256]; // image name
- CHAR LoadedImageName[256]; // symbol file name
-};
-
-
- // SymCleanup()
- typedef BOOL (__stdcall *tSC)( IN HANDLE hProcess );
- tSC pSC;
-
- // SymFunctionTableAccess64()
- typedef PVOID (__stdcall *tSFTA)( HANDLE hProcess, DWORD64 AddrBase );
- tSFTA pSFTA;
-
- // SymGetLineFromAddr64()
- typedef BOOL (__stdcall *tSGLFA)( IN HANDLE hProcess, IN DWORD64 dwAddr,
- OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line );
- tSGLFA pSGLFA;
-
- // SymGetModuleBase64()
- typedef DWORD64 (__stdcall *tSGMB)( IN HANDLE hProcess, IN DWORD64 dwAddr );
- tSGMB pSGMB;
-
- // SymGetModuleInfo64()
- typedef BOOL (__stdcall *tSGMI)( IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V2 *ModuleInfo );
- tSGMI pSGMI;
-
-// // SymGetModuleInfo64()
-// typedef BOOL (__stdcall *tSGMI_V3)( IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V3 *ModuleInfo );
-// tSGMI_V3 pSGMI_V3;
-
- // SymGetOptions()
- typedef DWORD (__stdcall *tSGO)( VOID );
- tSGO pSGO;
-
- // SymGetSymFromAddr64()
- typedef BOOL (__stdcall *tSGSFA)( IN HANDLE hProcess, IN DWORD64 dwAddr,
- OUT PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol );
- tSGSFA pSGSFA;
-
- // SymInitialize()
- typedef BOOL (__stdcall *tSI)( IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess );
- tSI pSI;
-
- // SymLoadModule64()
- typedef DWORD64 (__stdcall *tSLM)( IN HANDLE hProcess, IN HANDLE hFile,
- IN PSTR ImageName, IN PSTR ModuleName, IN DWORD64 BaseOfDll, IN DWORD SizeOfDll );
- tSLM pSLM;
-
- // SymSetOptions()
- typedef DWORD (__stdcall *tSSO)( IN DWORD SymOptions );
- tSSO pSSO;
-
- // StackWalk64()
- typedef BOOL (__stdcall *tSW)(
- DWORD MachineType,
- HANDLE hProcess,
- HANDLE hThread,
- LPSTACKFRAME64 StackFrame,
- PVOID ContextRecord,
- PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
- PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
- PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
- PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress );
- tSW pSW;
-
- // UnDecorateSymbolName()
- typedef DWORD (__stdcall WINAPI *tUDSN)( PCSTR DecoratedName, PSTR UnDecoratedName,
- DWORD UndecoratedLength, DWORD Flags );
- tUDSN pUDSN;
-
- typedef BOOL (__stdcall WINAPI *tSGSP)(HANDLE hProcess, PSTR SearchPath, DWORD SearchPathLength);
- tSGSP pSGSP;
-
-
-private:
- // **************************************** ToolHelp32 ************************
- #define MAX_MODULE_NAME32 255
- #define TH32CS_SNAPMODULE 0x00000008
- #pragma pack( push, 8 )
- typedef struct tagMODULEENTRY32
- {
- DWORD dwSize;
- DWORD th32ModuleID; // This module
- DWORD th32ProcessID; // owning process
- DWORD GlblcntUsage; // Global usage count on the module
- DWORD ProccntUsage; // Module usage count in th32ProcessID's context
- BYTE * modBaseAddr; // Base address of module in th32ProcessID's context
- DWORD modBaseSize; // Size in bytes of module starting at modBaseAddr
- HMODULE hModule; // The hModule of this module in th32ProcessID's context
- char szModule[MAX_MODULE_NAME32 + 1];
- char szExePath[MAX_PATH];
- } MODULEENTRY32;
- typedef MODULEENTRY32 * PMODULEENTRY32;
- typedef MODULEENTRY32 * LPMODULEENTRY32;
- #pragma pack( pop )
-
- BOOL GetModuleListTH32(HANDLE hProcess, DWORD pid)
- {
- // CreateToolhelp32Snapshot()
- typedef HANDLE (__stdcall *tCT32S)(DWORD dwFlags, DWORD th32ProcessID);
- // Module32First()
- typedef BOOL (__stdcall *tM32F)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
- // Module32Next()
- typedef BOOL (__stdcall *tM32N)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
-
- // try both dlls...
- const TCHAR *dllname[] = { _T("kernel32.dll"), _T("tlhelp32.dll") };
- HINSTANCE hToolhelp = NULL;
- tCT32S pCT32S = NULL;
- tM32F pM32F = NULL;
- tM32N pM32N = NULL;
-
- HANDLE hSnap;
- MODULEENTRY32 me;
- me.dwSize = sizeof(me);
- BOOL keepGoing;
- size_t i;
-
- for (i = 0; i<(sizeof(dllname) / sizeof(dllname[0])); i++ )
- {
- hToolhelp = LoadLibrary( dllname[i] );
- if (hToolhelp == NULL)
- continue;
- pCT32S = (tCT32S) GetProcAddress(hToolhelp, "CreateToolhelp32Snapshot");
- pM32F = (tM32F) GetProcAddress(hToolhelp, "Module32First");
- pM32N = (tM32N) GetProcAddress(hToolhelp, "Module32Next");
- if ( (pCT32S != NULL) && (pM32F != NULL) && (pM32N != NULL) )
- break; // found the functions!
- FreeLibrary(hToolhelp);
- hToolhelp = NULL;
- }
-
- if (hToolhelp == NULL)
- return FALSE;
-
- hSnap = pCT32S( TH32CS_SNAPMODULE, pid );
- if (hSnap == (HANDLE) -1)
- return FALSE;
-
- keepGoing = !!pM32F( hSnap, &me );
- int cnt = 0;
- while (keepGoing)
- {
- this->LoadModule(hProcess, me.szExePath, me.szModule, (DWORD64) me.modBaseAddr, me.modBaseSize);
- cnt++;
- keepGoing = !!pM32N( hSnap, &me );
- }
- CloseHandle(hSnap);
- FreeLibrary(hToolhelp);
- if (cnt <= 0)
- return FALSE;
- return TRUE;
- } // GetModuleListTH32
-
- // **************************************** PSAPI ************************
- typedef struct _MODULEINFO {
- LPVOID lpBaseOfDll;
- DWORD SizeOfImage;
- LPVOID EntryPoint;
- } MODULEINFO, *LPMODULEINFO;
-
- BOOL GetModuleListPSAPI(HANDLE hProcess)
- {
- // EnumProcessModules()
- typedef BOOL (__stdcall *tEPM)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded );
- // GetModuleFileNameEx()
- typedef DWORD (__stdcall *tGMFNE)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize );
- // GetModuleBaseName()
- typedef DWORD (__stdcall *tGMBN)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize );
- // GetModuleInformation()
- typedef BOOL (__stdcall *tGMI)(HANDLE hProcess, HMODULE hModule, LPMODULEINFO pmi, DWORD nSize );
-
- HINSTANCE hPsapi;
- tEPM pEPM;
- tGMFNE pGMFNE;
- tGMBN pGMBN;
- tGMI pGMI;
-
- DWORD i;
- //ModuleEntry e;
- DWORD cbNeeded;
- MODULEINFO mi;
- HMODULE *hMods = 0;
- char *tt = NULL;
- char *tt2 = NULL;
- const SIZE_T TTBUFLEN = 8096;
- int cnt = 0;
-
- hPsapi = LoadLibrary( _T("psapi.dll") );
- if (hPsapi == NULL)
- return FALSE;
-
- pEPM = (tEPM) GetProcAddress( hPsapi, "EnumProcessModules" );
- pGMFNE = (tGMFNE) GetProcAddress( hPsapi, "GetModuleFileNameExA" );
- pGMBN = (tGMFNE) GetProcAddress( hPsapi, "GetModuleBaseNameA" );
- pGMI = (tGMI) GetProcAddress( hPsapi, "GetModuleInformation" );
- if ( (pEPM == NULL) || (pGMFNE == NULL) || (pGMBN == NULL) || (pGMI == NULL) )
- {
- // we couldn´t find all functions
- FreeLibrary(hPsapi);
- return FALSE;
- }
-
- hMods = (HMODULE*) malloc(sizeof(HMODULE) * (TTBUFLEN / sizeof HMODULE));
- tt = (char*) malloc(sizeof(char) * TTBUFLEN);
- tt2 = (char*) malloc(sizeof(char) * TTBUFLEN);
- if ( (hMods == NULL) || (tt == NULL) || (tt2 == NULL) )
- goto cleanup;
-
- if ( ! pEPM( hProcess, hMods, TTBUFLEN, &cbNeeded ) )
- {
- //_ftprintf(fLogFile, _T("%lu: EPM failed, GetLastError = %lu\n"), g_dwShowCount, gle );
- goto cleanup;
- }
-
- if ( cbNeeded > TTBUFLEN )
- {
- //_ftprintf(fLogFile, _T("%lu: More than %lu module handles. Huh?\n"), g_dwShowCount, lenof( hMods ) );
- goto cleanup;
- }
-
- for ( i = 0; i < cbNeeded / sizeof hMods[0]; i++ )
- {
- // base address, size
- pGMI(hProcess, hMods[i], &mi, sizeof mi );
- // image file name
- tt[0] = 0;
- pGMFNE(hProcess, hMods[i], tt, TTBUFLEN );
- // module name
- tt2[0] = 0;
- pGMBN(hProcess, hMods[i], tt2, TTBUFLEN );
-
- DWORD dwRes = this->LoadModule(hProcess, tt, tt2, (DWORD64) mi.lpBaseOfDll, mi.SizeOfImage);
- if (dwRes != ERROR_SUCCESS)
- this->m_parent->OnDbgHelpErr("LoadModule", dwRes, 0);
- cnt++;
- }
-
- cleanup:
- if (hPsapi != NULL) FreeLibrary(hPsapi);
- if (tt2 != NULL) free(tt2);
- if (tt != NULL) free(tt);
- if (hMods != NULL) free(hMods);
-
- return cnt != 0;
- } // GetModuleListPSAPI
-
- DWORD LoadModule(HANDLE hProcess, LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size)
- {
- CHAR *szImg = _strdup(img);
- CHAR *szMod = _strdup(mod);
- DWORD result = ERROR_SUCCESS;
- if ( (szImg == NULL) || (szMod == NULL) )
- result = ERROR_NOT_ENOUGH_MEMORY;
- else
- {
- if (pSLM(hProcess, 0, szImg, szMod, baseAddr, size) == 0)
- result = GetLastError();
- }
- ULONGLONG fileVersion = 0;
- if ( (m_parent != NULL) && (szImg != NULL) )
- {
- // try to retrive the file-version:
- if ( (this->m_parent->m_options & StackWalker::RetrieveFileVersion) != 0)
- {
- VS_FIXEDFILEINFO *fInfo = NULL;
- DWORD dwHandle;
- DWORD dwSize = GetFileVersionInfoSizeA(szImg, &dwHandle);
- if (dwSize > 0)
- {
- LPVOID vData = malloc(dwSize);
- if (vData != NULL)
- {
- if (GetFileVersionInfoA(szImg, NULL /* dwHandle reserved */, dwSize, vData) != 0)
- {
- UINT len;
- TCHAR szSubBlock[] = _T("\\");
- if (VerQueryValue(vData, szSubBlock, (LPVOID*) &fInfo, &len) == 0)
- fInfo = NULL;
- else
- {
- fileVersion = ((ULONGLONG)fInfo->dwFileVersionLS) + ((ULONGLONG)fInfo->dwFileVersionMS << 32);
- }
- }
- free(vData);
- }
- }
- }
-
- // Retrive some additional-infos about the module
- IMAGEHLP_MODULE64_V2 Module;
- const char *szSymType = "-unknown-";
- if (this->GetModuleInfo(hProcess, baseAddr, &Module) != FALSE)
- {
- switch(Module.SymType)
- {
- case SymNone:
- szSymType = "-nosymbols-";
- break;
- case SymCoff:
- szSymType = "COFF";
- break;
- case SymCv:
- szSymType = "CV";
- break;
- case SymPdb:
- szSymType = "PDB";
- break;
- case SymExport:
- szSymType = "-exported-";
- break;
- case SymDeferred:
- szSymType = "-deferred-";
- break;
- case SymSym:
- szSymType = "SYM";
- break;
- case 8: //SymVirtual:
- szSymType = "Virtual";
- break;
- case 9: // SymDia:
- szSymType = "DIA";
- break;
- }
- }
- this->m_parent->OnLoadModule(img, mod, baseAddr, size, result, szSymType, Module.LoadedImageName, fileVersion);
- }
- if (szImg != NULL) free(szImg);
- if (szMod != NULL) free(szMod);
- return result;
- }
-public:
- BOOL LoadModules(HANDLE hProcess, DWORD dwProcessId)
- {
- // first try toolhelp32
- if (GetModuleListTH32(hProcess, dwProcessId))
- return true;
- // then try psapi
- return GetModuleListPSAPI(hProcess);
- }
-
-
- BOOL GetModuleInfo(HANDLE hProcess, DWORD64 baseAddr, IMAGEHLP_MODULE64_V2 *pModuleInfo)
- {
- if(this->pSGMI == NULL)
- {
- SetLastError(ERROR_DLL_INIT_FAILED);
- return FALSE;
- }
- // First try to use the larger ModuleInfo-Structure
-// memset(pModuleInfo, 0, sizeof(IMAGEHLP_MODULE64_V3));
-// pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V3);
-// if (this->pSGMI_V3 != NULL)
-// {
-// if (this->pSGMI_V3(hProcess, baseAddr, pModuleInfo) != FALSE)
-// return TRUE;
-// // check if the parameter was wrong (size is bad...)
-// if (GetLastError() != ERROR_INVALID_PARAMETER)
-// return FALSE;
-// }
- // could not retrive the bigger structure, try with the smaller one (as defined in VC7.1)...
- pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V2);
- void *pData = malloc(4096); // reserve enough memory, so the bug in v6.3.5.1 does not lead to memory-overwrites...
- if (pData == NULL)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
- memcpy(pData, pModuleInfo, sizeof(IMAGEHLP_MODULE64_V2));
- if (this->pSGMI(hProcess, baseAddr, (IMAGEHLP_MODULE64_V2*) pData) != FALSE)
- {
- // only copy as much memory as is reserved...
- memcpy(pModuleInfo, pData, sizeof(IMAGEHLP_MODULE64_V2));
- pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V2);
- free(pData);
- return TRUE;
- }
- free(pData);
- SetLastError(ERROR_DLL_INIT_FAILED);
- return FALSE;
- }
-};
-
-// #############################################################
-StackWalker::StackWalker(DWORD dwProcessId, HANDLE hProcess)
-{
- this->m_options = OptionsAll;
- this->m_modulesLoaded = FALSE;
- this->m_hProcess = hProcess;
- this->m_sw = new StackWalkerInternal(this, this->m_hProcess);
- this->m_dwProcessId = dwProcessId;
- this->m_szSymPath = NULL;
-}
-StackWalker::StackWalker(int options, LPCSTR szSymPath, DWORD dwProcessId, HANDLE hProcess)
-{
- this->m_options = options;
- this->m_modulesLoaded = FALSE;
- this->m_hProcess = hProcess;
- this->m_sw = new StackWalkerInternal(this, this->m_hProcess);
- this->m_dwProcessId = dwProcessId;
- if (szSymPath != NULL)
- {
- this->m_szSymPath = _strdup(szSymPath);
- this->m_options |= SymBuildPath;
- }
- else
- this->m_szSymPath = NULL;
-}
-
-StackWalker::~StackWalker()
-{
- if (m_szSymPath != NULL)
- free(m_szSymPath);
- m_szSymPath = NULL;
- if (this->m_sw != NULL)
- delete this->m_sw;
- this->m_sw = NULL;
-}
-
-BOOL StackWalker::LoadModules()
-{
- if (this->m_sw == NULL)
- {
- SetLastError(ERROR_DLL_INIT_FAILED);
- return FALSE;
- }
- if (m_modulesLoaded != FALSE)
- return TRUE;
-
- // Build the sym-path:
- char *szSymPath = NULL;
- if ( (this->m_options & SymBuildPath) != 0)
- {
- const size_t nSymPathLen = 4096;
- szSymPath = (char*) malloc(nSymPathLen);
- if (szSymPath == NULL)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
- szSymPath[0] = 0;
- // Now first add the (optional) provided sympath:
- if (this->m_szSymPath != NULL)
- {
- strcat_s(szSymPath, nSymPathLen, this->m_szSymPath);
- strcat_s(szSymPath, nSymPathLen, ";");
- }
-
- strcat_s(szSymPath, nSymPathLen, ".;");
-
- const size_t nTempLen = 1024;
- char szTemp[nTempLen];
- // Now add the current directory:
- if (GetCurrentDirectoryA(nTempLen, szTemp) > 0)
- {
- szTemp[nTempLen-1] = 0;
- strcat_s(szSymPath, nSymPathLen, szTemp);
- strcat_s(szSymPath, nSymPathLen, ";");
- }
-
- // Now add the path for the main-module:
- if (GetModuleFileNameA(NULL, szTemp, nTempLen) > 0)
- {
- szTemp[nTempLen-1] = 0;
- for (char *p = (szTemp+strlen(szTemp)-1); p >= szTemp; --p)
- {
- // locate the rightmost path separator
- if ( (*p == '\\') || (*p == '/') || (*p == ':') )
- {
- *p = 0;
- break;
- }
- } // for (search for path separator...)
- if (strlen(szTemp) > 0)
- {
- strcat_s(szSymPath, nSymPathLen, szTemp);
- strcat_s(szSymPath, nSymPathLen, ";");
- }
- }
- if (GetEnvironmentVariableA("_NT_SYMBOL_PATH", szTemp, nTempLen) > 0)
- {
- szTemp[nTempLen-1] = 0;
- strcat_s(szSymPath, nSymPathLen, szTemp);
- strcat_s(szSymPath, nSymPathLen, ";");
- }
- if (GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", szTemp, nTempLen) > 0)
- {
- szTemp[nTempLen-1] = 0;
- strcat_s(szSymPath, nSymPathLen, szTemp);
- strcat_s(szSymPath, nSymPathLen, ";");
- }
- if (GetEnvironmentVariableA("SYSTEMROOT", szTemp, nTempLen) > 0)
- {
- szTemp[nTempLen-1] = 0;
- strcat_s(szSymPath, nSymPathLen, szTemp);
- strcat_s(szSymPath, nSymPathLen, ";");
- // also add the "system32"-directory:
- strcat_s(szTemp, nTempLen, "\\system32");
- strcat_s(szSymPath, nSymPathLen, szTemp);
- strcat_s(szSymPath, nSymPathLen, ";");
- }
-
- if ( (this->m_options & SymBuildPath) != 0)
- {
- if (GetEnvironmentVariableA("SYSTEMDRIVE", szTemp, nTempLen) > 0)
- {
- szTemp[nTempLen-1] = 0;
- strcat_s(szSymPath, nSymPathLen, "SRV*");
- strcat_s(szSymPath, nSymPathLen, szTemp);
- strcat_s(szSymPath, nSymPathLen, "\\websymbols");
- strcat_s(szSymPath, nSymPathLen, "*http://msdl.microsoft.com/download/symbols;");
- }
- else
- strcat_s(szSymPath, nSymPathLen, "SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols;");
- }
- }
-
- // First Init the whole stuff...
- BOOL bRet = this->m_sw->Init(szSymPath);
- if (szSymPath != NULL) free(szSymPath); szSymPath = NULL;
- if (bRet == FALSE)
- {
- this->OnDbgHelpErr("Error while initializing dbghelp.dll", 0, 0);
- SetLastError(ERROR_DLL_INIT_FAILED);
- return FALSE;
- }
-
- bRet = this->m_sw->LoadModules(this->m_hProcess, this->m_dwProcessId);
- if (bRet != FALSE)
- m_modulesLoaded = TRUE;
- return bRet;
-}
-
-
-// The following is used to pass the "userData"-Pointer to the user-provided readMemoryFunction
-// This has to be done due to a problem with the "hProcess"-parameter in x64...
-// Because this class is in no case multi-threading-enabled (because of the limitations
-// of dbghelp.dll) it is "safe" to use a static-variable
-static StackWalker::PReadProcessMemoryRoutine s_readMemoryFunction = NULL;
-static LPVOID s_readMemoryFunction_UserData = NULL;
-
-BOOL StackWalker::ShowCallstack(HANDLE hThread, const CONTEXT *context, PReadProcessMemoryRoutine readMemoryFunction, LPVOID pUserData)
-{
- CONTEXT c;;
- CallstackEntry csEntry;
- IMAGEHLP_SYMBOL64 *pSym = NULL;
- StackWalkerInternal::IMAGEHLP_MODULE64_V2 Module;
- IMAGEHLP_LINE64 Line;
- int frameNum;
-
- if (m_modulesLoaded == FALSE)
- this->LoadModules(); // ignore the result...
-
- if (this->m_sw->m_hDbhHelp == NULL)
- {
- SetLastError(ERROR_DLL_INIT_FAILED);
- return FALSE;
- }
-
- s_readMemoryFunction = readMemoryFunction;
- s_readMemoryFunction_UserData = pUserData;
-
- if (context == NULL)
- {
- // If no context is provided, capture the context
- if (hThread == GetCurrentThread())
- {
- GET_CURRENT_CONTEXT(c, USED_CONTEXT_FLAGS);
- }
- else
- {
- SuspendThread(hThread);
- memset(&c, 0, sizeof(CONTEXT));
- c.ContextFlags = USED_CONTEXT_FLAGS;
- if (GetThreadContext(hThread, &c) == FALSE)
- {
- ResumeThread(hThread);
- return FALSE;
- }
- }
- }
- else
- c = *context;
-
- // init STACKFRAME for first call
- STACKFRAME64 s; // in/out stackframe
- memset(&s, 0, sizeof(s));
- DWORD imageType;
-#ifdef _M_IX86
- // normally, call ImageNtHeader() and use machine info from PE header
- imageType = IMAGE_FILE_MACHINE_I386;
- s.AddrPC.Offset = c.Eip;
- s.AddrPC.Mode = AddrModeFlat;
- s.AddrFrame.Offset = c.Ebp;
- s.AddrFrame.Mode = AddrModeFlat;
- s.AddrStack.Offset = c.Esp;
- s.AddrStack.Mode = AddrModeFlat;
-#elif _M_X64
- imageType = IMAGE_FILE_MACHINE_AMD64;
- s.AddrPC.Offset = c.Rip;
- s.AddrPC.Mode = AddrModeFlat;
- s.AddrFrame.Offset = c.Rsp;
- s.AddrFrame.Mode = AddrModeFlat;
- s.AddrStack.Offset = c.Rsp;
- s.AddrStack.Mode = AddrModeFlat;
-#elif _M_IA64
- imageType = IMAGE_FILE_MACHINE_IA64;
- s.AddrPC.Offset = c.StIIP;
- s.AddrPC.Mode = AddrModeFlat;
- s.AddrFrame.Offset = c.IntSp;
- s.AddrFrame.Mode = AddrModeFlat;
- s.AddrBStore.Offset = c.RsBSP;
- s.AddrBStore.Mode = AddrModeFlat;
- s.AddrStack.Offset = c.IntSp;
- s.AddrStack.Mode = AddrModeFlat;
-#else
-#error "Platform not supported!"
-#endif
-
- pSym = (IMAGEHLP_SYMBOL64 *) malloc(sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN);
- if (!pSym) goto cleanup; // not enough memory...
- memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN);
- pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
- pSym->MaxNameLength = STACKWALK_MAX_NAMELEN;
-
- memset(&Line, 0, sizeof(Line));
- Line.SizeOfStruct = sizeof(Line);
-
- memset(&Module, 0, sizeof(Module));
- Module.SizeOfStruct = sizeof(Module);
-
- for (frameNum = 0; ; ++frameNum )
- {
- // get next stack frame (StackWalk64(), SymFunctionTableAccess64(), SymGetModuleBase64())
- // if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can
- // assume that either you are done, or that the stack is so hosed that the next
- // deeper frame could not be found.
- // CONTEXT need not to be suplied if imageTyp is IMAGE_FILE_MACHINE_I386!
- if ( ! this->m_sw->pSW(imageType, this->m_hProcess, hThread, &s, &c, myReadProcMem, this->m_sw->pSFTA, this->m_sw->pSGMB, NULL) )
- {
- this->OnDbgHelpErr("StackWalk64", GetLastError(), s.AddrPC.Offset);
- break;
- }
-
- csEntry.offset = s.AddrPC.Offset;
- csEntry.name[0] = 0;
- csEntry.undName[0] = 0;
- csEntry.undFullName[0] = 0;
- csEntry.offsetFromSmybol = 0;
- csEntry.offsetFromLine = 0;
- csEntry.lineFileName[0] = 0;
- csEntry.lineNumber = 0;
- csEntry.loadedImageName[0] = 0;
- csEntry.moduleName[0] = 0;
- if (s.AddrPC.Offset == s.AddrReturn.Offset)
- {
- this->OnDbgHelpErr("StackWalk64-Endless-Callstack!", 0, s.AddrPC.Offset);
- break;
- }
- if (s.AddrPC.Offset != 0)
- {
- // we seem to have a valid PC
- // show procedure info (SymGetSymFromAddr64())
- if (this->m_sw->pSGSFA(this->m_hProcess, s.AddrPC.Offset, &(csEntry.offsetFromSmybol), pSym) != FALSE)
- {
- // TODO: Mache dies sicher...!
- strcpy_s(csEntry.name, pSym->Name);
- // UnDecorateSymbolName()
- this->m_sw->pUDSN( pSym->Name, csEntry.undName, STACKWALK_MAX_NAMELEN, UNDNAME_NAME_ONLY );
- this->m_sw->pUDSN( pSym->Name, csEntry.undFullName, STACKWALK_MAX_NAMELEN, UNDNAME_COMPLETE );
- }
- else
- {
- this->OnDbgHelpErr("SymGetSymFromAddr64", GetLastError(), s.AddrPC.Offset);
- }
-
- // show line number info, NT5.0-method (SymGetLineFromAddr64())
- if (this->m_sw->pSGLFA != NULL )
- { // yes, we have SymGetLineFromAddr64()
- if (this->m_sw->pSGLFA(this->m_hProcess, s.AddrPC.Offset, &(csEntry.offsetFromLine), &Line) != FALSE)
- {
- csEntry.lineNumber = Line.LineNumber;
- // TODO: Mache dies sicher...!
- strcpy_s(csEntry.lineFileName, Line.FileName);
- }
- else
- {
- this->OnDbgHelpErr("SymGetLineFromAddr64", GetLastError(), s.AddrPC.Offset);
- }
- } // yes, we have SymGetLineFromAddr64()
-
- // show module info (SymGetModuleInfo64())
- if (this->m_sw->GetModuleInfo(this->m_hProcess, s.AddrPC.Offset, &Module ) != FALSE)
- { // got module info OK
- switch ( Module.SymType )
- {
- case SymNone:
- csEntry.symTypeString = "-nosymbols-";
- break;
- case SymCoff:
- csEntry.symTypeString = "COFF";
- break;
- case SymCv:
- csEntry.symTypeString = "CV";
- break;
- case SymPdb:
- csEntry.symTypeString = "PDB";
- break;
- case SymExport:
- csEntry.symTypeString = "-exported-";
- break;
- case SymDeferred:
- csEntry.symTypeString = "-deferred-";
- break;
- case SymSym:
- csEntry.symTypeString = "SYM";
- break;
-#if API_VERSION_NUMBER >= 9
- case SymDia:
- csEntry.symTypeString = "DIA";
- break;
-#endif
- case 8: //SymVirtual:
- csEntry.symTypeString = "Virtual";
- break;
- default:
- //_snprintf( ty, sizeof ty, "symtype=%ld", (long) Module.SymType );
- csEntry.symTypeString = NULL;
- break;
- }
-
- // TODO: Mache dies sicher...!
- strcpy_s(csEntry.moduleName, Module.ModuleName);
- csEntry.baseOfImage = Module.BaseOfImage;
- strcpy_s(csEntry.loadedImageName, Module.LoadedImageName);
- } // got module info OK
- else
- {
- this->OnDbgHelpErr("SymGetModuleInfo64", GetLastError(), s.AddrPC.Offset);
- }
- } // we seem to have a valid PC
-
- CallstackEntryType et = nextEntry;
- if (frameNum == 0)
- et = firstEntry;
- this->OnCallstackEntry(et, csEntry);
-
- if (s.AddrReturn.Offset == 0)
- {
- this->OnCallstackEntry(lastEntry, csEntry);
- SetLastError(ERROR_SUCCESS);
- break;
- }
- } // for ( frameNum )
-
- cleanup:
- if (pSym) free( pSym );
-
- if (context == NULL)
- ResumeThread(hThread);
-
- return TRUE;
-}
-
-BOOL __stdcall StackWalker::myReadProcMem(
- HANDLE hProcess,
- DWORD64 qwBaseAddress,
- PVOID lpBuffer,
- DWORD nSize,
- LPDWORD lpNumberOfBytesRead
- )
-{
- if (s_readMemoryFunction == NULL)
- {
- SIZE_T st;
- BOOL bRet = ReadProcessMemory(hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, &st);
- *lpNumberOfBytesRead = (DWORD) st;
- //printf("ReadMemory: hProcess: %p, baseAddr: %p, buffer: %p, size: %d, read: %d, result: %d\n", hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, (DWORD) st, (DWORD) bRet);
- return bRet;
- }
- else
- {
- return s_readMemoryFunction(hProcess, qwBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead, s_readMemoryFunction_UserData);
- }
-}
-
-void StackWalker::OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion)
-{
- /*CHAR buffer[STACKWALK_MAX_NAMELEN];
- if (fileVersion == 0)
- _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s'\n", img, mod, (LPVOID) baseAddr, size, result, symType, pdbName);
- else
- {
- DWORD v4 = (DWORD) fileVersion & 0xFFFF;
- DWORD v3 = (DWORD) (fileVersion>>16) & 0xFFFF;
- DWORD v2 = (DWORD) (fileVersion>>32) & 0xFFFF;
- DWORD v1 = (DWORD) (fileVersion>>48) & 0xFFFF;
- _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s', fileVersion: %d.%d.%d.%d\n", img, mod, (LPVOID) baseAddr, size, result, symType, pdbName, v1, v2, v3, v4);
- }
- OnOutput(buffer);*/
-}
-
-void StackWalker::OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry)
-{
- CHAR buffer[STACKWALK_MAX_NAMELEN];
- if ( (eType != lastEntry) && (entry.offset != 0) )
- {
- if (entry.name[0] == 0)
- strcpy_s(entry.name, "(function-name not available)");
- if (entry.undName[0] != 0)
- strcpy_s(entry.name, entry.undName);
- if (entry.undFullName[0] != 0)
- strcpy_s(entry.name, entry.undFullName);
- if (entry.lineFileName[0] == 0)
- {
- strcpy_s(entry.lineFileName, "(filename not available)");
- if (entry.moduleName[0] == 0)
- strcpy_s(entry.moduleName, "(module-name not available)");
- _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "%p (%s): %s: %s\n", (LPVOID) entry.offset, entry.moduleName, entry.lineFileName, entry.name);
- }
- else
- _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "%s (%d): %s\n", entry.lineFileName, entry.lineNumber, entry.name);
- OnOutput(buffer);
- }
-}
-
-void StackWalker::OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr)
-{
- CHAR buffer[STACKWALK_MAX_NAMELEN];
- _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "ERROR: %s, GetLastError: %d (Address: %p)\n", szFuncName, gle, (LPVOID) addr);
- OnOutput(buffer);
-}
-
-void StackWalker::OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName)
-{
- /*CHAR buffer[STACKWALK_MAX_NAMELEN];
- _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "SymInit: Symbol-SearchPath: '%s', symOptions: %d, UserName: '%s'\n", szSearchPath, symOptions, szUserName);
- OnOutput(buffer);*/
-// // Also display the OS-version
-//#if _MSC_VER <= 1200
-// OSVERSIONINFOA ver;
-// ZeroMemory(&ver, sizeof(OSVERSIONINFOA));
-// ver.dwOSVersionInfoSize = sizeof(ver);
-// if (GetVersionExA(&ver) != FALSE)
-// {
-// _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "OS-Version: %d.%d.%d (%s)\n",
-// ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,
-// ver.szCSDVersion);
-// OnOutput(buffer);
-// }
-//#else
-// OSVERSIONINFOEXA ver;
-// ZeroMemory(&ver, sizeof(OSVERSIONINFOEXA));
-// ver.dwOSVersionInfoSize = sizeof(ver);
-// if (GetVersionExA( (OSVERSIONINFOA*) &ver) != FALSE)
-// {
-// _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "OS-Version: %d.%d.%d (%s) 0x%x-0x%x\n",
-// ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,
-// ver.szCSDVersion, ver.wSuiteMask, ver.wProductType);
-// OnOutput(buffer);
-// }
-//#endif
-}
-
-void StackWalker::OnOutput(LPCSTR buffer)
-{
- OutputDebugStringA(buffer);
-}
diff --git a/src/3rd-party/StackWalker/StackWalker.h b/src/3rd-party/StackWalker/StackWalker.h
deleted file mode 100644
index 67498217..00000000
--- a/src/3rd-party/StackWalker/StackWalker.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/**********************************************************************
- *
- * StackWalker.h
- *
- *
- * History:
- * 2005-07-27 v1 - First public release on http://www.codeproject.com/
- * (for additional changes see History in 'StackWalker.cpp'!
- *
- **********************************************************************/
-// #pragma once is supported starting with _MCS_VER 1000,
-// so we need not to check the version (because we only support _MSC_VER >= 1100)!
-#pragma once
-
-// special defines for VC5/6 (if no actual PSDK is installed):
-#if _MSC_VER < 1300
-typedef unsigned __int64 DWORD64, *PDWORD64;
-#if defined(_WIN64)
-typedef unsigned __int64 SIZE_T, *PSIZE_T;
-#else
-typedef unsigned long SIZE_T, *PSIZE_T;
-#endif
-#endif // _MSC_VER < 1300
-
-class StackWalkerInternal; // forward
-class StackWalker
-{
-public:
- typedef enum StackWalkOptions
- {
- // No addition info will be retrived
- // (only the address is available)
- RetrieveNone = 0,
-
- // Try to get the symbol-name
- RetrieveSymbol = 1,
-
- // Try to get the line for this symbol
- RetrieveLine = 2,
-
- // Try to retrieve the module-infos
- RetrieveModuleInfo = 4,
-
- // Also retrieve the version for the DLL/EXE
- RetrieveFileVersion = 8,
-
- // Contains all the abouve
- RetrieveVerbose = 0xF,
-
- // Generate a "good" symbol-search-path
- SymBuildPath = 0x10,
-
- // Also use the public Microsoft-Symbol-Server
- SymUseSymSrv = 0x20,
-
- // Contains all the abouve "Sym"-options
- SymAll = 0x30,
-
- // Contains all options (default)
- OptionsAll = 0x3F
- } StackWalkOptions;
-
- StackWalker(
- int options = OptionsAll, // 'int' is by design, to combine the enum-flags
- LPCSTR szSymPath = NULL,
- DWORD dwProcessId = GetCurrentProcessId(),
- HANDLE hProcess = GetCurrentProcess()
- );
- StackWalker(DWORD dwProcessId, HANDLE hProcess);
- virtual ~StackWalker();
-
- typedef BOOL (__stdcall *PReadProcessMemoryRoutine)(
- HANDLE hProcess,
- DWORD64 qwBaseAddress,
- PVOID lpBuffer,
- DWORD nSize,
- LPDWORD lpNumberOfBytesRead,
- LPVOID pUserData // optional data, which was passed in "ShowCallstack"
- );
-
- BOOL LoadModules();
-
- BOOL ShowCallstack(
- HANDLE hThread = GetCurrentThread(),
- const CONTEXT *context = NULL,
- PReadProcessMemoryRoutine readMemoryFunction = NULL,
- LPVOID pUserData = NULL // optional to identify some data in the 'readMemoryFunction'-callback
- );
-
-#if _MSC_VER >= 1300
-// due to some reasons, the "STACKWALK_MAX_NAMELEN" must be declared as "public"
-// in older compilers in order to use it... starting with VC7 we can declare it as "protected"
-protected:
-#endif
- enum { STACKWALK_MAX_NAMELEN = 1024 }; // max name length for found symbols
-
-protected:
- // Entry for each Callstack-Entry
- typedef struct CallstackEntry
- {
- DWORD64 offset; // if 0, we have no valid entry
- CHAR name[STACKWALK_MAX_NAMELEN];
- CHAR undName[STACKWALK_MAX_NAMELEN];
- CHAR undFullName[STACKWALK_MAX_NAMELEN];
- DWORD64 offsetFromSmybol;
- DWORD offsetFromLine;
- DWORD lineNumber;
- CHAR lineFileName[STACKWALK_MAX_NAMELEN];
- DWORD symType;
- LPCSTR symTypeString;
- CHAR moduleName[STACKWALK_MAX_NAMELEN];
- DWORD64 baseOfImage;
- CHAR loadedImageName[STACKWALK_MAX_NAMELEN];
- } CallstackEntry;
-
- enum CallstackEntryType {firstEntry, nextEntry, lastEntry};
-
- virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName);
- virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion);
- virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry);
- virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr);
- virtual void OnOutput(LPCSTR szText);
-
- StackWalkerInternal *m_sw;
- HANDLE m_hProcess;
- DWORD m_dwProcessId;
- BOOL m_modulesLoaded;
- LPSTR m_szSymPath;
-
- int m_options;
-
- static BOOL __stdcall myReadProcMem(HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead);
-
- friend StackWalkerInternal;
-};
-
-
-// The "ugly" assembler-implementation is needed for systems before XP
-// If you have a new PSDK and you only compile for XP and later, then you can use
-// the "RtlCaptureContext"
-// Currently there is no define which determines the PSDK-Version...
-// So we just use the compiler-version (and assumes that the PSDK is
-// the one which was installed by the VS-IDE)
-
-// INFO: If you want, you can use the RtlCaptureContext if you only target XP and later...
-// But I currently use it in x64/IA64 environments...
-//#if defined(_M_IX86) && (_WIN32_WINNT <= 0x0500) && (_MSC_VER < 1400)
-
-#if defined(_M_IX86)
-#ifdef CURRENT_THREAD_VIA_EXCEPTION
-// TODO: The following is not a "good" implementation,
-// because the callstack is only valid in the "__except" block...
-#define GET_CURRENT_CONTEXT(c, contextFlags) \
- do { \
- memset(&c, 0, sizeof(CONTEXT)); \
- EXCEPTION_POINTERS *pExp = NULL; \
- __try { \
- throw 0; \
- } __except( ( (pExp = GetExceptionInformation()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_EXECUTE_HANDLER)) {} \
- if (pExp != NULL) \
- memcpy(&c, pExp->ContextRecord, sizeof(CONTEXT)); \
- c.ContextFlags = contextFlags; \
- } while(0);
-#else
-// The following should be enough for walking the callstack...
-#define GET_CURRENT_CONTEXT(c, contextFlags) \
- do { \
- memset(&c, 0, sizeof(CONTEXT)); \
- c.ContextFlags = contextFlags; \
- __asm call x \
- __asm x: pop eax \
- __asm mov c.Eip, eax \
- __asm mov c.Ebp, ebp \
- __asm mov c.Esp, esp \
- } while(0);
-#endif
-
-#else
-
-// The following is defined for x86 (XP and higher), x64 and IA64:
-#define GET_CURRENT_CONTEXT(c, contextFlags) \
- do { \
- memset(&c, 0, sizeof(CONTEXT)); \
- c.ContextFlags = contextFlags; \
- RtlCaptureContext(&c); \
-} while(0);
-#endif
diff --git a/src/kiwano-audio/AudioEngine.cpp b/src/kiwano-audio/AudioEngine.cpp
index 2b155787..d060e31f 100644
--- a/src/kiwano-audio/AudioEngine.cpp
+++ b/src/kiwano-audio/AudioEngine.cpp
@@ -75,36 +75,51 @@ namespace kiwano
dlls::MediaFoundation::Get().MFShutdown();
}
- HRESULT AudioEngine::CreateVoice(IXAudio2SourceVoice** voice, const Transcoder::Buffer& buffer)
+ bool AudioEngine::CreateSound(Sound& sound, const Transcoder::Buffer& buffer)
{
KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
- if (voice == nullptr)
+ HRESULT hr = S_OK;
+
+ if (buffer.format == nullptr)
+ hr = E_INVALIDARG;
+
+ if (SUCCEEDED(hr))
{
- return E_INVALIDARG;
+ IXAudio2SourceVoice* voice = nullptr;
+ hr = x_audio2_->CreateSourceVoice(&voice, buffer.format, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
+
+ if (SUCCEEDED(hr))
+ {
+ IXAudio2SourceVoice* old = sound.GetXAudio2Voice();
+ if (old)
+ {
+ old->DestroyVoice();
+ old = nullptr;
+ }
+
+ sound.SetXAudio2Voice(voice);
+ }
}
- if (*voice)
- {
- (*voice)->DestroyVoice();
- (*voice) = nullptr;
- }
-
- return x_audio2_->CreateSourceVoice(voice, buffer.format, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
+ win32::WarnIfFailed(hr);
+ return SUCCEEDED(hr);
}
void AudioEngine::Open()
{
KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
- x_audio2_->StartEngine();
+ if (x_audio2_)
+ x_audio2_->StartEngine();
}
void AudioEngine::Close()
{
KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
- x_audio2_->StopEngine();
+ if (x_audio2_)
+ x_audio2_->StopEngine();
}
}
}
diff --git a/src/kiwano-audio/AudioEngine.h b/src/kiwano-audio/AudioEngine.h
index 4a5de063..4321ac3a 100644
--- a/src/kiwano-audio/AudioEngine.h
+++ b/src/kiwano-audio/AudioEngine.h
@@ -22,12 +22,27 @@
#include
#include
#include
+#include
#include
namespace kiwano
{
namespace audio
{
+ /**
+ * \~chinese
+ * \defgroup Audio ÒôƵÒýÇæ
+ */
+
+ /**
+ * \addtogroup Audio
+ * @{
+ */
+
+ /**
+ * \~chinese
+ * @brief ÒôƵÒýÇæ
+ */
class KGE_API AudioEngine
: public Singleton
, public ComponentBase
@@ -35,16 +50,17 @@ namespace kiwano
friend Singleton;
public:
- // ¿ªÆôÉ豸
+ /// \~chinese
+ /// @brief ¿ªÆôÒôƵÉ豸
void Open();
- // ¹Ø±ÕÉ豸
+ /// \~chinese
+ /// @brief ¹Ø±ÕÒôƵÉ豸
void Close();
- HRESULT CreateVoice(
- IXAudio2SourceVoice** voice,
- const Transcoder::Buffer& buffer
- );
+ /// \~chinese
+ /// @brief ´Ó½âÂëÆ÷Êý¾Ý»º³åÖд´½¨ÒôƵ¶ÔÏó
+ bool CreateSound(Sound& sound, const Transcoder::Buffer& buffer);
public:
void SetupComponent() override;
@@ -60,5 +76,7 @@ namespace kiwano
IXAudio2* x_audio2_;
IXAudio2MasteringVoice* mastering_voice_;
};
+
+ /** @} */
}
}
diff --git a/src/kiwano-audio/Sound.cpp b/src/kiwano-audio/Sound.cpp
index 8e503f31..be9bcdc2 100644
--- a/src/kiwano-audio/Sound.cpp
+++ b/src/kiwano-audio/Sound.cpp
@@ -35,18 +35,6 @@ namespace kiwano
{
}
- Sound::Sound(String const& file_path)
- : Sound()
- {
- Load(file_path);
- }
-
- Sound::Sound(Resource const& res)
- : Sound()
- {
- Load(res);
- }
-
Sound::~Sound()
{
Close();
@@ -68,19 +56,15 @@ namespace kiwano
String full_path = FileSystem::instance().GetFullPathForFile(file_path);
HRESULT hr = transcoder_.LoadMediaFile(full_path);
-
if (FAILED(hr))
{
KGE_ERROR(L"Load media file failed with HRESULT of %08X", hr);
return false;
}
- hr = AudioEngine::instance().CreateVoice(&voice_, transcoder_.GetBuffer());
- if (FAILED(hr))
+ if (!AudioEngine::instance().CreateSound(*this, transcoder_.GetBuffer()))
{
Close();
-
- KGE_ERROR(L"Create source voice failed with HRESULT of %08X", hr);
return false;
}
@@ -96,19 +80,15 @@ namespace kiwano
}
HRESULT hr = transcoder_.LoadMediaResource(res);
-
if (FAILED(hr))
{
KGE_ERROR(L"Load media resource failed with HRESULT of %08X", hr);
return false;
}
- hr = AudioEngine::instance().CreateVoice(&voice_, transcoder_.GetBuffer());
- if (FAILED(hr))
+ if (!AudioEngine::instance().CreateSound(*this, transcoder_.GetBuffer()))
{
Close();
-
- KGE_ERROR(L"Create source voice failed with HRESULT of %08X", hr);
return false;
}
@@ -116,6 +96,11 @@ namespace kiwano
return true;
}
+ bool Sound::IsValid() const
+ {
+ return voice_ != nullptr;
+ }
+
void Sound::Play(int loop_count)
{
if (!opened_)
diff --git a/src/kiwano-audio/Sound.h b/src/kiwano-audio/Sound.h
index a247d307..c1a1a1ac 100644
--- a/src/kiwano-audio/Sound.h
+++ b/src/kiwano-audio/Sound.h
@@ -21,6 +21,7 @@
#pragma once
#include
#include
+#include
#include
#include
@@ -28,68 +29,100 @@ namespace kiwano
{
namespace audio
{
+ class AudioEngine;
+
KGE_DECLARE_SMART_PTR(Sound);
+ /**
+ * \addtogroup Audio
+ * @{
+ */
+
+ /**
+ * \~chinese
+ * @brief 񙮵
+ */
class KGE_API Sound
: public ObjectBase
{
+ friend class AudioEngine;
+
public:
Sound();
- Sound(
- String const& file_path /* ±¾µØÒôƵÎļþ */
- );
-
- Sound(
- Resource const& res /* ÒôÀÖ×ÊÔ´ */
- );
-
virtual ~Sound();
- // ´ò¿ª±¾µØÒôƵÎļþ
- bool Load(
- String const& file_path
- );
+ /// \~chinese
+ /// @brief ´ò¿ª±¾µØÒôƵÎļþ
+ /// @param res ±¾µØÒôƵÎļþ·¾¶
+ bool Load(String const& file_path);
- // ´ò¿ªÒôÀÖ×ÊÔ´
- bool Load(
- Resource const& res /* ÒôÀÖ×ÊÔ´ */
- );
+ /// \~chinese
+ /// @brief ´ò¿ªÒôƵ×ÊÔ´
+ /// @param res ÒôƵ×ÊÔ´
+ bool Load(Resource const& res);
- // ²¥·Å
- void Play(
- int loop_count = 0 /* ²¥·ÅÑ»·´ÎÊý (-1 Ϊѻ·²¥·Å) */
- );
+ /// \~chinese
+ /// @brief ÊÇ·ñÓÐЧ
+ bool IsValid() const;
- // ÔÝÍ£
+ /// \~chinese
+ /// @brief ²¥·Å
+ /// @param loop_count ²¥·ÅÑ»·´ÎÊý£¬ÉèÖà -1 Ϊѻ·²¥·Å
+ void Play(int loop_count = 0);
+
+ /// \~chinese
+ /// @brief ÔÝÍ£
void Pause();
- // ¼ÌÐø
+ /// \~chinese
+ /// @brief ¼ÌÐø
void Resume();
- // ֹͣ
+ /// \~chinese
+ /// @brief ֹͣ
void Stop();
- // ¹Ø±Õ²¢»ØÊÕ×ÊÔ´
+ /// \~chinese
+ /// @brief ¹Ø±Õ²¢Ïú»Ù×ÊÔ´
void Close();
- // ÊÇ·ñÕýÔÚ²¥·Å
+ /// \~chinese
+ /// @brief ÊÇ·ñÕýÔÚ²¥·Å
bool IsPlaying() const;
- // »ñÈ¡ÒôÁ¿
+ /// \~chinese
+ /// @brief »ñÈ¡ÒôÁ¿
float GetVolume() const;
- // ÉèÖÃÒôÁ¿
- void SetVolume(
- float volume /* 1 ΪÔʼÒôÁ¿, ´óÓÚ 1 Ϊ·Å´óÒôÁ¿, 0 Ϊ×îСÒôÁ¿ */
- );
+ /// \~chinese
+ /// @brief ÉèÖÃÒôÁ¿
+ /// @param volume ÒôÁ¿´óС£¬1.0 ΪÔʼÒôÁ¿, ´óÓÚ 1 Ϊ·Å´óÒôÁ¿, 0 Ϊ×îСÒôÁ¿
+ void SetVolume(float volume);
private:
- bool opened_;
- bool playing_;
- Transcoder transcoder_;
+ IXAudio2SourceVoice* GetXAudio2Voice() const;
+ void SetXAudio2Voice(IXAudio2SourceVoice* voice);
+
+ private:
+ bool opened_;
+ bool playing_;
+ Transcoder transcoder_;
IXAudio2SourceVoice* voice_;
};
+
+ /** @} */
+
+
+ inline IXAudio2SourceVoice* Sound::GetXAudio2Voice() const
+ {
+ return voice_;
+ }
+
+ inline void Sound::SetXAudio2Voice(IXAudio2SourceVoice* voice)
+ {
+ voice_ = voice;
+ }
}
}
diff --git a/src/kiwano-audio/SoundPlayer.h b/src/kiwano-audio/SoundPlayer.h
index 1b3f94f8..f3bd7809 100644
--- a/src/kiwano-audio/SoundPlayer.h
+++ b/src/kiwano-audio/SoundPlayer.h
@@ -28,69 +28,84 @@ namespace kiwano
{
KGE_DECLARE_SMART_PTR(SoundPlayer);
- // ÒôÀÖ²¥·ÅÆ÷
+ /**
+ * \addtogroup Audio
+ * @{
+ */
+
+ /**
+ * \~chinese
+ * @brief ÒôƵ²¥·ÅÆ÷
+ */
class KGE_API SoundPlayer
- : protected ObjectBase
+ : public ObjectBase
{
public:
SoundPlayer();
~SoundPlayer();
- // ¼ÓÔØ±¾µØÒôƵÎļþ, ·µ»Ø¸Ã×ÊÔ´µÄ±êʶ·û
- size_t Load(
- String const& file_path
- );
+ /// \~chinese
+ /// @brief ¼ÓÔØ±¾µØÒôƵÎļþ
+ /// @param file_path ±¾µØÒôƵÎļþ·¾¶
+ /// @return ÒôƵ±êʶ·û
+ size_t Load(String const& file_path);
- // ¼ÓÔØÒôÀÖ×ÊÔ´, ·µ»Ø¸Ã×ÊÔ´µÄ±êʶ·û
- size_t Load(
- Resource const& res /* ÒôÀÖ×ÊÔ´ */
- );
+ /// \~chinese
+ /// @brief ¼ÓÔØÒôƵ×ÊÔ´
+ /// @param res ÒôƵ×ÊÔ´
+ /// @return ÒôƵ±êʶ·û
+ size_t Load(Resource const& res);
- // ²¥·ÅÒôÀÖ
- void Play(
- size_t id, /* ±êʶ·û */
- int loop_count = 0 /* ²¥·ÅÑ»·´ÎÊý (-1 Ϊѻ·²¥·Å) */
- );
+ /// \~chinese
+ /// @brief ²¥·ÅÒôƵ
+ /// @param id ÒôƵ±êʶ·û
+ /// @param loop_count ²¥·ÅÑ»·´ÎÊý£¬ÉèÖà -1 Ϊѻ·²¥·Å
+ void Play(size_t id, int loop_count = 0);
- // ÔÝÍ£ÒôÀÖ
- void Pause(
- size_t id /* ±êʶ·û */
- );
+ /// \~chinese
+ /// @brief ÔÝÍ£ÒôƵ
+ /// @param id ÒôƵ±êʶ·û
+ void Pause(size_t id);
- // ¼ÌÐø²¥·ÅÒôÀÖ
- void Resume(
- size_t id /* ±êʶ·û */
- );
+ /// \~chinese
+ /// @brief ¼ÌÐø²¥·ÅÒôƵ
+ /// @param id ÒôƵ±êʶ·û
+ void Resume(size_t id);
- // Í£Ö¹ÒôÀÖ
- void Stop(
- size_t id /* ±êʶ·û */
- );
+ /// \~chinese
+ /// @brief Í£Ö¹ÒôƵ
+ /// @param id ÒôƵ±êʶ·û
+ void Stop(size_t id);
- // »ñÈ¡ÒôÀÖ²¥·Å״̬
- bool IsPlaying(
- size_t id /* ±êʶ·û */
- );
+ /// \~chinese
+ /// @brief »ñÈ¡ÒôƵ²¥·Å״̬
+ /// @param id ÒôƵ±êʶ·û
+ bool IsPlaying(size_t id);
- // »ñÈ¡ÒôÁ¿
+ /// \~chinese
+ /// @brief »ñÈ¡ÒôÁ¿
float GetVolume() const;
- // ÉèÖÃÒôÁ¿
- void SetVolume(
- float volume /* 1.0 ΪÔʼÒôÁ¿ */
- );
+ /// \~chinese
+ /// @brief ÉèÖÃÒôÁ¿
+ /// @param volume ÒôÁ¿´óС£¬1.0 ΪÔʼÒôÁ¿, ´óÓÚ 1 Ϊ·Å´óÒôÁ¿, 0 Ϊ×îСÒôÁ¿
+ void SetVolume(float volume);
- // ÔÝÍ£ËùÓÐÒôÀÖ
+ /// \~chinese
+ /// @brief ÔÝÍ£ËùÓÐÒôƵ
void PauseAll();
- // ¼ÌÐø²¥·ÅËùÓÐÒôÀÖ
+ /// \~chinese
+ /// @brief ¼ÌÐø²¥·ÅËùÓÐÒôƵ
void ResumeAll();
- // Í£Ö¹ËùÓÐÒôÀÖ
+ /// \~chinese
+ /// @brief Í£Ö¹ËùÓÐÒôƵ
void StopAll();
- // Çå³ý»º´æ
+ /// \~chinese
+ /// @brief Çå³ý»º´æ
void ClearCache();
private:
@@ -99,5 +114,7 @@ namespace kiwano
using SoundMap = Map;
SoundMap sound_cache_;
};
+
+ /** @} */
}
}
diff --git a/src/kiwano-audio/Transcoder.h b/src/kiwano-audio/Transcoder.h
index 1ee99cf3..50afd1c0 100644
--- a/src/kiwano-audio/Transcoder.h
+++ b/src/kiwano-audio/Transcoder.h
@@ -28,41 +28,64 @@ namespace kiwano
{
namespace audio
{
+ class Sound;
+ /**
+ * \addtogroup Audio
+ * @{
+ */
+
+ /**
+ * \~chinese
+ * @brief ÒôƵ½âÂëÆ÷
+ */
class KGE_API Transcoder
{
+ friend class Sound;
+
public:
+ /**
+ * \~chinese
+ * @brief ÒôƵÊý¾Ý»º³å
+ */
struct Buffer
{
- BYTE* data;
- uint32_t size;
- const WAVEFORMATEX* format;
+ BYTE* data; ///< ÒôƵÊý¾Ý
+ uint32_t size; ///< ÒôƵÊý¾Ý´óС
+ const WAVEFORMATEX* format; ///< ÒôƵÊý¾Ý¸ñʽ
};
Transcoder();
~Transcoder();
+ /// \~chinese
+ /// @brief »ñÈ¡Êý¾Ý»º³å
Buffer GetBuffer() const;
+ /// \~chinese
+ /// @brief Çå¿ÕÊý¾Ý»º³å
void ClearBuffer();
- HRESULT LoadMediaFile(
- String const& file_path
- );
+ private:
+ /// \~chinese
+ /// @brief ½âÂë±¾µØÒôƵÎļþ
+ HRESULT LoadMediaFile(String const& file_path);
- HRESULT LoadMediaResource(
- Resource const& res
- );
+ /// \~chinese
+ /// @brief ½âÂëÒôƵ×ÊÔ´
+ HRESULT LoadMediaResource(Resource const& res);
- HRESULT ReadSource(
- IMFSourceReader* reader
- );
+ /// \~chinese
+ /// @brief ¶ÁÈ¡ÒôƵԴÊý¾Ý
+ HRESULT ReadSource(IMFSourceReader* reader);
private:
BYTE* wave_data_;
uint32_t wave_size_;
WAVEFORMATEX* wave_format_;
};
+
+ /** @} */
}
}
diff --git a/src/kiwano-audio/libraries.cpp b/src/kiwano-audio/libraries.cpp
index 8523bfea..5239d216 100644
--- a/src/kiwano-audio/libraries.cpp
+++ b/src/kiwano-audio/libraries.cpp
@@ -33,9 +33,9 @@ namespace kiwano
{
const auto xaudio2_dll_names =
{
- L"xaudio2_9.dll", // for Windows 10
- L"xaudio2_8.dll", // for Windows 8
- L"xaudio2_7.dll" // for DirectX SDK
+ "xaudio2_9.dll", // for Windows 10
+ "xaudio2_8.dll", // for Windows 8
+ "xaudio2_7.dll" // for DirectX SDK
};
for (const auto& name : xaudio2_dll_names)
@@ -48,7 +48,7 @@ namespace kiwano
if (xaudio2.IsValid())
{
- XAudio2Create = xaudio2.GetProcess(L"XAudio2Create");
+ XAudio2Create = xaudio2.GetProcess("XAudio2Create");
}
else
{
@@ -68,28 +68,28 @@ namespace kiwano
, MFCreateSourceReaderFromByteStream(nullptr)
, MFCreateMFByteStreamOnStream(nullptr)
{
- if (mfplat.Load(L"Mfplat.dll"))
+ if (mfplat.Load("Mfplat.dll"))
{
- MFStartup = mfplat.GetProcess(L"MFStartup");
- MFShutdown = mfplat.GetProcess(L"MFShutdown");
- MFCreateMediaType = mfplat.GetProcess(L"MFCreateMediaType");
- MFCreateWaveFormatExFromMFMediaType = mfplat.GetProcess(L"MFCreateWaveFormatExFromMFMediaType");
- MFCreateMFByteStreamOnStream = mfplat.GetProcess(L"MFCreateMFByteStreamOnStream");
+ MFStartup = mfplat.GetProcess("MFStartup");
+ MFShutdown = mfplat.GetProcess("MFShutdown");
+ MFCreateMediaType = mfplat.GetProcess("MFCreateMediaType");
+ MFCreateWaveFormatExFromMFMediaType = mfplat.GetProcess("MFCreateWaveFormatExFromMFMediaType");
+ MFCreateMFByteStreamOnStream = mfplat.GetProcess("MFCreateMFByteStreamOnStream");
}
else
{
- KGE_SYS_LOG(L"Load Mfplat.dll failed");
+ KGE_ERROR(L"Load Mfplat.dll failed");
throw std::runtime_error("Load Mfplat.dll failed");
}
- if (mfreadwrite.Load(L"Mfreadwrite.dll"))
+ if (mfreadwrite.Load("Mfreadwrite.dll"))
{
- MFCreateSourceReaderFromURL = mfreadwrite.GetProcess(L"MFCreateSourceReaderFromURL");
- MFCreateSourceReaderFromByteStream = mfreadwrite.GetProcess(L"MFCreateSourceReaderFromByteStream");
+ MFCreateSourceReaderFromURL = mfreadwrite.GetProcess("MFCreateSourceReaderFromURL");
+ MFCreateSourceReaderFromByteStream = mfreadwrite.GetProcess("MFCreateSourceReaderFromByteStream");
}
else
{
- KGE_SYS_LOG(L"Load Mfreadwrite.dll failed");
+ KGE_ERROR(L"Load Mfreadwrite.dll failed");
throw std::runtime_error("Load Mfreadwrite.dll failed");
}
}
diff --git a/src/kiwano-audio/libraries.h b/src/kiwano-audio/libraries.h
index f40db8ba..44d26bf7 100644
--- a/src/kiwano-audio/libraries.h
+++ b/src/kiwano-audio/libraries.h
@@ -25,6 +25,8 @@
#include
#include
+#ifndef KGE_DOXYGEN_DO_NOT_INCLUDE
+
namespace kiwano
{
namespace audio
@@ -93,3 +95,5 @@ namespace kiwano
}
}
}
+
+#endif
diff --git a/src/kiwano-imgui/ImGuiLayer.h b/src/kiwano-imgui/ImGuiLayer.h
index f2928783..8f4246b2 100644
--- a/src/kiwano-imgui/ImGuiLayer.h
+++ b/src/kiwano-imgui/ImGuiLayer.h
@@ -27,8 +27,14 @@ namespace kiwano
{
KGE_DECLARE_SMART_PTR(ImGuiLayer);
+ /// \~chinese
+ /// @brief ImGui¹ÜµÀ
using ImGuiPipeline = Function;
+ /**
+ * \~chinese
+ * @brief ImGuiͼ²ã
+ */
class ImGuiLayer
: public Layer
{
@@ -37,18 +43,20 @@ namespace kiwano
virtual ~ImGuiLayer();
- // Ìí¼Ó ImGui ÔªËØ
- void AddItem(
- ImGuiPipeline const& item,
- String const& name
- );
+ /// \~chinese
+ /// @brief Ìí¼Ó ImGui ÔªËØ
+ /// @param item ¹ÜµÀ
+ /// @param name ÔªËØÃû³Æ
+ void AddItem(ImGuiPipeline const& item, String const& name);
- // ÒÆ³ý ImGui ÔªËØ
- void RemoveItem(
- String const& name
- );
+ /// \~chinese
+ /// @brief ÒÆ³ý ImGui ÔªËØ
+ /// @param name ÔªËØÃû³Æ
+ void RemoveItem(String const& name);
// ÒÆ³ýËùÓÐÔªËØ
+ /// \~chinese
+ /// @brief ÒÆ³ýËùÓÐÔªËØ
void RemoveAllItems();
public:
diff --git a/src/kiwano-imgui/ImGuiModule.h b/src/kiwano-imgui/ImGuiModule.h
index 17fa3db5..50e50115 100644
--- a/src/kiwano-imgui/ImGuiModule.h
+++ b/src/kiwano-imgui/ImGuiModule.h
@@ -26,6 +26,10 @@ namespace kiwano
{
namespace imgui
{
+ /**
+ * \~chinese
+ * @brief ImGuiÄ£¿é
+ */
class ImGuiModule
: public Singleton
, public RenderComponent
@@ -34,13 +38,6 @@ namespace kiwano
{
friend Singleton;
- private:
- void Init(HWND hwnd);
-
- void NewFrame();
-
- void Render();
-
public:
ImGuiModule();
@@ -48,14 +45,21 @@ namespace kiwano
void DestroyComponent() override;
- void OnUpdate(Duration dt) override;
-
void BeforeRender() override;
void AfterRender() override;
void HandleMessage(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) override;
+ void OnUpdate(Duration dt) override;
+
+ private:
+ void Init(HWND hwnd);
+
+ void NewFrame();
+
+ void Render();
+
void UpdateMousePos();
void UpdateMouseCursor();
diff --git a/src/kiwano-imgui/imgui_impl.h b/src/kiwano-imgui/imgui_impl.h
index d010cf30..372f26fe 100644
--- a/src/kiwano-imgui/imgui_impl.h
+++ b/src/kiwano-imgui/imgui_impl.h
@@ -2,6 +2,8 @@
#pragma once
+#ifndef KGE_DOXYGEN_DO_NOT_INCLUDE
+
#if !defined(KGE_USE_DIRECTX10)
#include
@@ -27,3 +29,5 @@ inline void ImGui_Impl_InvalidateDeviceObjects() { ImGui_ImplDX10_Invalid
inline bool ImGui_Impl_CreateDeviceObjects() { return ImGui_ImplDX10_CreateDeviceObjects(); }
#endif
+
+#endif
diff --git a/src/kiwano-imgui/imgui_impl_dx10.h b/src/kiwano-imgui/imgui_impl_dx10.h
index 8e994ee9..26fdb0c1 100644
--- a/src/kiwano-imgui/imgui_impl_dx10.h
+++ b/src/kiwano-imgui/imgui_impl_dx10.h
@@ -3,6 +3,8 @@
#pragma once
#include <3rd-party/imgui/imgui.h>
+#ifndef KGE_DOXYGEN_DO_NOT_INCLUDE
+
struct ID3D10Device;
IMGUI_IMPL_API bool ImGui_ImplDX10_Init(ID3D10Device* device);
@@ -13,3 +15,5 @@ IMGUI_IMPL_API void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data);
// Use if you want to reset your rendering device without losing ImGui state.
IMGUI_IMPL_API void ImGui_ImplDX10_InvalidateDeviceObjects();
IMGUI_IMPL_API bool ImGui_ImplDX10_CreateDeviceObjects();
+
+#endif
diff --git a/src/kiwano-imgui/imgui_impl_dx11.h b/src/kiwano-imgui/imgui_impl_dx11.h
index 066c4ba2..4964c00c 100644
--- a/src/kiwano-imgui/imgui_impl_dx11.h
+++ b/src/kiwano-imgui/imgui_impl_dx11.h
@@ -3,6 +3,8 @@
#pragma once
#include <3rd-party/imgui/imgui.h>
+#ifndef KGE_DOXYGEN_DO_NOT_INCLUDE
+
struct ID3D11Device;
struct ID3D11DeviceContext;
@@ -14,3 +16,5 @@ IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
// Use if you want to reset your rendering device without losing ImGui state.
IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
+
+#endif
diff --git a/src/kiwano-network/HttpClient.cpp b/src/kiwano-network/HttpClient.cpp
index d0c3db54..65b0305d 100644
--- a/src/kiwano-network/HttpClient.cpp
+++ b/src/kiwano-network/HttpClient.cpp
@@ -36,7 +36,7 @@ namespace
uint32_t write_data(void* buffer, uint32_t size, uint32_t nmemb, void* userp)
{
- oc::string* recv_buffer = (oc::string*)userp;
+ ByteString* recv_buffer = (ByteString*)userp;
uint32_t total = size * nmemb;
// add data to the end of recv_buffer
@@ -46,10 +46,10 @@ namespace
return total;
}
- oc::string convert_to_utf8(oc::wstring const& str)
+ ByteString convert_to_utf8(String const& str)
{
std::wstring_convert> utf8_conv;
- oc::string result;
+ ByteString result;
try
{
@@ -58,15 +58,15 @@ namespace
catch (std::range_error&)
{
// bad conversion
- result = wide_to_string(str);
+ result = WideToMultiByte(str);
}
return result;
}
- oc::wstring convert_from_utf8(oc::string const& str)
+ String convert_from_utf8(ByteString const& str)
{
oc::string_convert> utf8_conv;
- oc::wstring result;
+ String result;
try
{
@@ -75,7 +75,7 @@ namespace
catch (std::range_error&)
{
// bad conversion
- result = string_to_wide(str);
+ result = MultiByteToWide(str);
}
return result;
}
@@ -104,7 +104,7 @@ namespace
}
}
- bool Init(HttpClient* client, Vector const& headers, oc::string const& url, oc::string* response_data, oc::string* response_header, char* error_buffer)
+ bool Init(HttpClient* client, Vector const& headers, ByteString const& url, ByteString* response_data, ByteString* response_header, char* error_buffer)
{
if (!SetOption(CURLOPT_ERRORBUFFER, error_buffer))
return false;
@@ -170,11 +170,11 @@ namespace
public:
static inline bool GetRequest(
HttpClient* client,
- Vector const& headers,
- oc::string const& url,
+ Vector const& headers,
+ ByteString const& url,
long* response_code,
- oc::string* response_data,
- oc::string* response_header,
+ ByteString* response_data,
+ ByteString* response_header,
char* error_buffer)
{
Curl curl;
@@ -185,12 +185,12 @@ namespace
static inline bool PostRequest(
HttpClient* client,
- Vector const& headers,
- oc::string const& url,
- oc::string const& request_data,
+ Vector const& headers,
+ ByteString const& url,
+ ByteString const& request_data,
long* response_code,
- oc::string* response_data,
- oc::string* response_header,
+ ByteString* response_data,
+ ByteString* response_header,
char* error_buffer)
{
Curl curl;
@@ -203,12 +203,12 @@ namespace
static inline bool PutRequest(
HttpClient* client,
- Vector const& headers,
- oc::string const& url,
- oc::string const& request_data,
+ Vector const& headers,
+ ByteString const& url,
+ ByteString const& request_data,
long* response_code,
- oc::string* response_data,
- oc::string* response_header,
+ ByteString* response_data,
+ ByteString* response_header,
char* error_buffer)
{
Curl curl;
@@ -221,11 +221,11 @@ namespace
static inline bool DeleteRequest(
HttpClient* client,
- Vector const& headers,
- oc::string const& url,
+ Vector const& headers,
+ ByteString const& url,
long* response_code,
- oc::string* response_data,
- oc::string* response_header,
+ ByteString* response_data,
+ ByteString* response_header,
char* error_buffer)
{
Curl curl;
@@ -307,13 +307,13 @@ namespace kiwano
bool ok = false;
long response_code = 0;
char error_message[256] = { 0 };
- oc::string response_header;
- oc::string response_data;
+ ByteString response_header;
+ ByteString response_data;
- oc::string url = convert_to_utf8(request->GetUrl());
- oc::string data = convert_to_utf8(request->GetData());
+ ByteString url = convert_to_utf8(request->GetUrl());
+ ByteString data = convert_to_utf8(request->GetData());
- Vector headers;
+ Vector headers;
headers.reserve(request->GetHeaders().size());
for (const auto& pair : request->GetHeaders())
{
@@ -340,12 +340,12 @@ namespace kiwano
}
response->SetResponseCode(response_code);
- response->SetHeader(oc::string_to_wide(response_header));
+ response->SetHeader(MultiByteToWide(response_header));
response->SetData(convert_from_utf8(response_data));
if (!ok)
{
response->SetSucceed(false);
- response->SetError(oc::string_to_wide(error_message));
+ response->SetError(MultiByteToWide(error_message));
}
else
{
diff --git a/src/kiwano-network/HttpClient.h b/src/kiwano-network/HttpClient.h
index 5e69be8d..600252ae 100644
--- a/src/kiwano-network/HttpClient.h
+++ b/src/kiwano-network/HttpClient.h
@@ -28,6 +28,20 @@ namespace kiwano
{
namespace network
{
+ /**
+ * \~chinese
+ * \defgroup Network ÍøÂçͨÐÅ
+ */
+
+ /**
+ * \addtogroup Network
+ * @{
+ */
+
+ /**
+ * \~chinese
+ * @brief HTTP¿Í»§¶Ë
+ */
class KGE_API HttpClient
: public Singleton
, public ComponentBase
@@ -35,18 +49,34 @@ namespace kiwano
friend Singleton;
public:
+ /// \~chinese
+ /// @brief ·¢ËÍHTTPÇëÇó
+ /// @param[in] request HTTPÇëÇó
+ /// @details ·¢ËÍÇëÇóºó£¬ÎÞÂÛ½áÊø»òʧ°Ü¶¼½«µ÷ÓÃÇëÇóµÄÏìÓ¦»Øµ÷º¯Êý
void Send(HttpRequestPtr request);
+ /// \~chinese
+ /// @brief ÉèÖÃÁ¬½Ó³¬Ê±Ê±³¤
void SetTimeoutForConnect(Duration timeout);
+ /// \~chinese
+ /// @brief »ñÈ¡Á¬½Ó³¬Ê±Ê±³¤
Duration GetTimeoutForConnect() const;
+ /// \~chinese
+ /// @brief ÉèÖöÁÈ¡³¬Ê±Ê±³¤
void SetTimeoutForRead(Duration timeout);
+ /// \~chinese
+ /// @brief »ñÈ¡¶ÁÈ¡³¬Ê±Ê±³¤
Duration GetTimeoutForRead() const;
+ /// \~chinese
+ /// @brief ÉèÖÃSSLÖ¤Ê鵨ַ
void SetSSLVerification(String const& root_certificate_path);
+ /// \~chinese
+ /// @brief »ñÈ¡SSLÖ¤Ê鵨ַ
String const& GetSSLVerification() const;
public:
@@ -59,10 +89,7 @@ namespace kiwano
void NetworkThread();
- void Perform(
- HttpRequestPtr request,
- HttpResponsePtr response
- );
+ void Perform(HttpRequestPtr request, HttpResponsePtr response);
void DispatchResponseCallback();
@@ -81,6 +108,8 @@ namespace kiwano
std::condition_variable_any sleep_condition_;
};
+ /** @} */
+
inline void HttpClient::SetTimeoutForConnect(Duration timeout)
{
diff --git a/src/kiwano-network/HttpRequest.h b/src/kiwano-network/HttpRequest.h
index 706e66f1..89dae6fa 100644
--- a/src/kiwano-network/HttpRequest.h
+++ b/src/kiwano-network/HttpRequest.h
@@ -31,46 +31,88 @@ namespace kiwano
KGE_DECLARE_SMART_PTR(HttpRequest);
+ /**
+ * \addtogroup Network
+ * @{
+ */
+
+ /**
+ * \~chinese
+ * @brief HTTPÇëÇó
+ */
class KGE_API HttpRequest
: public ObjectBase
{
public:
- using ResponseCallback = Function;
+ /// \~chinese
+ /// @brief ÏìÓ¦»Øµ÷º¯Êý
+ using ResponseCallback = Function;
+ /// \~chinese
+ /// @brief ÇëÇóÀàÐÍ
enum class Type
{
- Unknown,
- Get,
- Post,
- Put,
- Delete
+ Unknown, ///< δ֪
+ Get, ///< HTTP GETÇëÇó
+ Post, ///< HTTP POSTÇëÇó
+ Put, ///< HTTP PUTÇëÇó
+ Delete ///< HTTP DELETEÇëÇó
};
HttpRequest();
HttpRequest(Type type);
- // ÇëÇóµØÖ·
+ /// \~chinese
+ /// @brief ÉèÖÃÇëÇóµØÖ·
void SetUrl(String const& url);
+
+ /// \~chinese
+ /// @brief ÉèÖÃÇëÇóÀàÐÍ
+ void SetType(Type type);
+
+ /// \~chinese
+ /// @brief ÉèÖÃÇëÇóЯ´øµÄÊý¾Ý
+ void SetData(String const& data);
+
+ /// \~chinese
+ /// @brief ÉèÖÃÇëÇóЯ´øµÄJSONÊý¾Ý
+ void SetJsonData(Json const& json);
+
+ /// \~chinese
+ /// @brief ÉèÖÃHTTPÍ·
+ void SetHeaders(Map const& headers);
+
+ /// \~chinese
+ /// @brief ÉèÖÃHTTPÍ·
+ void SetHeader(String const& field, String const& content);
+
+ /// \~chinese
+ /// @brief ÉèÖÃÏìÓ¦»Øµ÷º¯Êý
+ void SetResponseCallback(ResponseCallback const& callback);
+
+ /// \~chinese
+ /// @brief »ñÈ¡ÇëÇóµØÖ·
String const& GetUrl() const;
- // ÇëÇóÀàÐÍ
- void SetType(Type type);
+ /// \~chinese
+ /// @brief »ñÈ¡ÇëÇóÀàÐÍ
Type GetType() const;
- // ÇëÇóÊý¾Ý
- void SetData(String const& data);
- void SetJsonData(Json const& json);
+ /// \~chinese
+ /// @brief »ñÈ¡ÇëÇóÊý¾Ý
String const& GetData() const;
- // ÇëÇóÍ·
- void SetHeaders(Map const& headers);
- void SetHeader(String const& field, String const& content);
+ /// \~chinese
+ /// @brief »ñÈ¡HTTPÍ·
Map& GetHeaders();
+
+ /// \~chinese
+ /// @brief »ñÈ¡HTTPÍ·
String const& GetHeader(String const& header) const;
- // ÏìÓ¦»Øµ÷
- void SetResponseCallback(ResponseCallback const& callback);
+ /// \~chinese
+ /// @brief »ñÈ¡ÏìÓ¦»Øµ÷º¯Êý
ResponseCallback const& GetResponseCallback() const;
private:
@@ -81,6 +123,8 @@ namespace kiwano
ResponseCallback response_cb_;
};
+ /** @} */
+
inline HttpRequest::HttpRequest() : type_(Type::Unknown) {}
inline HttpRequest::HttpRequest(Type type) : type_(type) {}
diff --git a/src/kiwano-network/HttpResponse.hpp b/src/kiwano-network/HttpResponse.hpp
index 5de8be60..14f80831 100644
--- a/src/kiwano-network/HttpResponse.hpp
+++ b/src/kiwano-network/HttpResponse.hpp
@@ -27,33 +27,63 @@ namespace kiwano
{
KGE_DECLARE_SMART_PTR(HttpResponse);
+ /**
+ * \addtogroup Network
+ * @{
+ */
+
+ /**
+ * \~chinese
+ * @brief HTTPÏìÓ¦
+ */
class KGE_API HttpResponse
: public ObjectBase
{
public:
HttpResponse(HttpRequestPtr request);
- // »ñÈ¡ÇëÇó
+ /// \~chinese
+ /// @brief »ñÈ¡¶ÔÓ¦µÄHTTPÇëÇó
HttpRequestPtr GetRequest() const;
- // ÏìӦ״̬
+ /// \~chinese
+ /// @brief »ñÈ¡ÏìӦ״̬
bool IsSucceed() const;
+
+ /// \~chinese
+ /// @brief »ñÈ¡HTTP״̬Âë
+ long GetResponseCode() const;
+
+ /// \~chinese
+ /// @brief »ñÈ¡ÏìӦͷ
+ String GetHeader() const;
+
+ /// \~chinese
+ /// @brief »ñÈ¡ÏìÓ¦Êý¾Ý
+ String const& GetData() const;
+
+ /// \~chinese
+ /// @brief »ñÈ¡´íÎóÐÅÏ¢
+ String const& GetError() const;
+
+ /// \~chinese
+ /// @brief ÉèÖÃÏìӦ״̬
void SetSucceed(bool succeed);
- // ÏìӦ״̬Âë
- long GetResponseCode() const;
+ /// \~chinese
+ /// @brief ÉèÖÃHTTP״̬Âë
void SetResponseCode(long response_code);
- // ÏìӦͷ
- String GetHeader() const;
+ /// \~chinese
+ /// @brief ÉèÖÃÏìӦͷ
void SetHeader(String const& response_header);
- // ÏìÓ¦Êý¾Ý
- String const& GetData() const;
+ /// \~chinese
+ /// @brief ÉèÖÃÏìÓ¦Êý¾Ý
void SetData(String const& response_data);
- // ´íÎóÐÅÏ¢
- String const& GetError() const;
+ /// \~chinese
+ /// @brief ÉèÖôíÎóÐÅÏ¢
void SetError(String const& error_buffer);
private:
@@ -66,6 +96,8 @@ namespace kiwano
String error_buffer_;
};
+ /** @} */
+
inline HttpResponse::HttpResponse(HttpRequestPtr request) : request_(request), succeed_(false), response_code_(0) {}
inline HttpRequestPtr HttpResponse::GetRequest() const { return request_; }
diff --git a/src/kiwano/2d/Actor.h b/src/kiwano/2d/Actor.h
index 2caa9497..30564cf0 100644
--- a/src/kiwano/2d/Actor.h
+++ b/src/kiwano/2d/Actor.h
@@ -38,7 +38,7 @@ namespace kiwano
/**
* \~chinese
- * \defgroup Actors ½ÇÉ«
+ * \defgroup Actors »ù´¡½ÇÉ«
*/
/**
@@ -63,8 +63,13 @@ namespace kiwano
friend IntrusiveList;
public:
- using Children = IntrusiveList;
- using UpdateCallback = Function;
+ /// \~chinese
+ /// @brief ×Ó³ÉÔ±Áбí
+ using Children = IntrusiveList;
+
+ /// \~chinese
+ /// @brief ½ÇÉ«¸üлص÷º¯Êý
+ using UpdateCallback = Function;
Actor();
@@ -395,15 +400,15 @@ namespace kiwano
protected:
/// \~chinese
- /// @brief ¸üÐÂ×ÔÉíºÍËùÓÐ×Ó½Úµã
+ /// @brief ¸üÐÂ×ÔÉíºÍËùÓÐ×Ó½ÇÉ«
virtual void Update(Duration dt);
/// \~chinese
- /// @brief äÖȾ×ÔÉíºÍËùÓÐ×Ó½Úµã
+ /// @brief äÖȾ×ÔÉíºÍËùÓÐ×Ó½ÇÉ«
virtual void Render(RenderTarget* rt);
/// \~chinese
- /// @brief »æÖÆ×ÔÉíºÍËùÓÐ×Ó½ÚµãµÄ±ß½ç
+ /// @brief »æÖÆ×ÔÉíºÍËùÓÐ×Ó½ÇÉ«µÄ±ß½ç
virtual void RenderBorder(RenderTarget* rt);
/// \~chinese
@@ -415,15 +420,15 @@ namespace kiwano
virtual void PrepareToRender(RenderTarget* rt);
/// \~chinese
- /// @brief ¸üÐÂ×Ô¼ºµÄ¶þά±ä»»£¬²¢Í¨ÖªËùÓÐ×Ó½Úµã
+ /// @brief ¸üÐÂ×Ô¼ºµÄ¶þά±ä»»£¬²¢Í¨ÖªËùÓÐ×Ó½ÇÉ«
void UpdateTransform() const;
/// \~chinese
- /// @brief ¸üÐÂ×Ô¼ººÍËùÓÐ×Ó½ÚµãµÄ͸Ã÷¶È
+ /// @brief ¸üÐÂ×Ô¼ººÍËùÓÐ×Ó½ÇÉ«µÄ͸Ã÷¶È
void UpdateOpacity();
/// \~chinese
- /// @brief ½«ËùÓÐ×ӽڵ㰴ZÖá˳ÐòÅÅÐò
+ /// @brief ½«ËùÓÐ×Ó½ÇÉ«°´ZÖá˳ÐòÅÅÐò
void Reorder();
/// \~chinese
diff --git a/src/kiwano/2d/Stage.h b/src/kiwano/2d/Stage.h
index cbbd5a0b..b7dff0a9 100644
--- a/src/kiwano/2d/Stage.h
+++ b/src/kiwano/2d/Stage.h
@@ -76,7 +76,7 @@ namespace kiwano
protected:
/// \~chinese
- /// @brief »æÖÆËùÓÐ×Ó½ÚµãµÄ±ß½ç
+ /// @brief »æÖÆËùÓÐ×Ó½ÇÉ«µÄ±ß½ç
void RenderBorder(RenderTarget* rt) override;
private:
diff --git a/src/kiwano/core/Library.cpp b/src/kiwano/core/Library.cpp
index fda1c0c0..49fb83c1 100644
--- a/src/kiwano/core/Library.cpp
+++ b/src/kiwano/core/Library.cpp
@@ -45,6 +45,12 @@ namespace kiwano
return IsValid();
}
+ bool Library::Load(ByteString const& lib)
+ {
+ instance_ = ::LoadLibraryA(lib.c_str());
+ return IsValid();
+ }
+
bool Library::IsValid() const
{
return instance_ != nullptr;
@@ -59,10 +65,13 @@ namespace kiwano
}
}
- FARPROC Library::GetProcess(String const& proc_name)
+ FARPROC Library::GetProcess(ByteString const& proc_name)
{
KGE_ASSERT(instance_ != nullptr);
- return GetProcAddress(instance_, oc::wide_to_string(proc_name).c_str());
+
+ if (!IsValid())
+ return nullptr;
+ return GetProcAddress(instance_, proc_name.c_str());
}
}
diff --git a/src/kiwano/core/Library.h b/src/kiwano/core/Library.h
index 6b7b8351..9d8ed576 100644
--- a/src/kiwano/core/Library.h
+++ b/src/kiwano/core/Library.h
@@ -47,6 +47,11 @@ namespace kiwano
/// @param lib DLLÎļþ·¾¶
bool Load(String const& lib);
+ /// \~chinese
+ /// @brief ¼ÓÔØDLL
+ /// @param lib DLLÎļþ·¾¶
+ bool Load(ByteString const& lib);
+
/// \~chinese
/// @brief ÊÇ·ñÓÐЧ
bool IsValid() const;
@@ -58,13 +63,13 @@ namespace kiwano
/// \~chinese
/// @brief ¼ìË÷Ö¸¶¨µÄDLLÖеÄÊä³ö¿âº¯ÊýµØÖ·
/// @param proc_name º¯ÊýÃû
- FARPROC GetProcess(String const& proc_name);
+ FARPROC GetProcess(ByteString const& proc_name);
/// \~chinese
/// @brief ¼ìË÷Ö¸¶¨µÄDLLÖеÄÊä³ö¿âº¯ÊýµØÖ·
/// @param proc_name º¯ÊýÃû
template
- inline _Proc GetProcess(String const& proc_name)
+ inline _Proc GetProcess(ByteString const& proc_name)
{
return reinterpret_cast<_Proc>(GetProcess(proc_name));
}
diff --git a/src/kiwano/core/Logger.cpp b/src/kiwano/core/Logger.cpp
index 2e03531c..624e1276 100644
--- a/src/kiwano/core/Logger.cpp
+++ b/src/kiwano/core/Logger.cpp
@@ -201,32 +201,29 @@ namespace kiwano
void Logger::Prepare(Level level, StringStream& sstream)
{
- String prompt;
+ String prefix;
switch (level)
{
case Level::Info:
- prompt = L"[INFO] ";
+ prefix = L"[INFO] ";
break;
case Level::System:
- prompt = L"[SYSTEM] ";
+ prefix = L"[SYSTEM] ";
break;
case Level::Warning:
- prompt = L"[WARNING] ";
+ prefix = L"[WARN] ";
break;
case Level::Error:
- prompt = L"[ERROR] ";
+ prefix = L"[ERROR] ";
break;
}
- // Prefix
- sstream << L"[KIWANO] " << prompt;
-
// Timestamp
time_t unix = std::time(nullptr);
std::tm tmbuf;
localtime_s(&tmbuf, &unix);
- sstream << std::put_time(&tmbuf, L"%H:%M:%S ");
+ sstream << prefix << std::put_time(&tmbuf, L"%H:%M:%S ");
}
void Logger::Output(Level level, StringStream& sstream)
diff --git a/src/kiwano/core/Logger.h b/src/kiwano/core/Logger.h
index eb2f2888..99b59364 100644
--- a/src/kiwano/core/Logger.h
+++ b/src/kiwano/core/Logger.h
@@ -78,18 +78,6 @@ namespace kiwano
/// @brief ¿ØÖÆÌ¨ÑÕÉ«
using ConsoleColor = Function;
- /// \~chinese
- /// @brief ÏÔʾ»ò¹Ø±Õ¿ØÖÆÌ¨
- void ShowConsole(bool show);
-
- /// \~chinese
- /// @brief ÆôÓÃÈÕÖ¾
- void Enable();
-
- /// \~chinese
- /// @brief ½ûÓÃÈÕÖ¾
- void Disable();
-
/// \~chinese
/// @brief ´òÓ¡ÈÕÖ¾
/// @param level ÈÕÖ¾¼¶±ð
@@ -110,6 +98,19 @@ namespace kiwano
template
void Println(Level level, _Args&& ... args);
+ /// \~chinese
+ /// @brief ÏÔʾ»ò¹Ø±Õ¿ØÖÆÌ¨
+ /// @note ´Ë²Ù×÷»áÖØÖÃÊä³öÁ÷
+ void ShowConsole(bool show);
+
+ /// \~chinese
+ /// @brief ÆôÓÃÈÕÖ¾
+ void Enable();
+
+ /// \~chinese
+ /// @brief ½ûÓÃÈÕÖ¾
+ void Disable();
+
/// \~chinese
/// @brief »ñÈ¡Êä³öÁ÷
std::wostream& GetOutputStream();
diff --git a/src/kiwano/core/common.h b/src/kiwano/core/common.h
index c3739608..7d72c318 100644
--- a/src/kiwano/core/common.h
+++ b/src/kiwano/core/common.h
@@ -37,6 +37,10 @@ namespace kiwano
/// @brief ×Ö·û´®ÈÝÆ÷
using String = oc::wstring;
+ /// \~chinese
+ /// @brief Õ×Ö·û´®ÈÝÆ÷
+ using ByteString = oc::string;
+
/// \~chinese
/// @brief ×Ö·û´®Á÷
using StringStream = std::wstringstream;
@@ -149,4 +153,14 @@ namespace kiwano
{
return oc::closure(ptr, func);
}
+
+ inline ByteString WideToMultiByte(const String& str)
+ {
+ return oc::wide_to_string(str);
+ }
+
+ inline String MultiByteToWide(const ByteString& str)
+ {
+ return oc::string_to_wide(str);
+ }
}
diff --git a/src/kiwano/platform/Window.cpp b/src/kiwano/platform/Window.cpp
index 376b6a7d..009ccced 100644
--- a/src/kiwano/platform/Window.cpp
+++ b/src/kiwano/platform/Window.cpp
@@ -128,13 +128,7 @@ namespace kiwano
uint32_t screenh = monitor_info_ex.rcWork.bottom - monitor_info_ex.rcWork.top;
uint32_t win_width, win_height;
- AdjustWindow(
- width,
- height,
- GetWindowStyle(),
- &win_width,
- &win_height
- );
+ AdjustWindow(width, height, GetWindowStyle(), &win_width, &win_height);
left = monitor_info_ex.rcWork.left + (screenw - win_width) / 2;
top = monitor_info_ex.rcWork.top + (screenh - win_height) / 2;
diff --git a/src/kiwano/platform/win32/StackWalker.cpp b/src/kiwano/platform/win32/StackWalker.cpp
new file mode 100644
index 00000000..47232140
--- /dev/null
+++ b/src/kiwano/platform/win32/StackWalker.cpp
@@ -0,0 +1,235 @@
+// Copyright (c) 2016-2018 Kiwano - Nomango
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include
+#include
+#include
+#include
+
+namespace kiwano
+{
+ namespace win32
+ {
+ namespace
+ {
+
+ // SymInitialize()
+ typedef BOOL(__stdcall* PFN_SymInitialize)(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess);
+
+ // SymCleanup()
+ typedef BOOL(__stdcall* PFN_SymCleanup)(IN HANDLE hProcess);
+
+ // SymGetLineFromAddr64()
+ typedef BOOL(__stdcall* PFN_SymGetLineFromAddr64)(IN HANDLE hProcess, IN DWORD64 dwAddr,
+ OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line);
+
+ // SymGetSymFromAddr64()
+ typedef BOOL(__stdcall* PFN_SymGetSymFromAddr64)(IN HANDLE hProcess, IN DWORD64 dwAddr,
+ OUT PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol);
+
+ // StackWalk64()
+ typedef BOOL(__stdcall* PFN_StackWalk64)(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
+ LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
+ PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
+ PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
+
+ // SymFunctionTableAccess64()
+ typedef PVOID(__stdcall* PFN_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase);
+
+ // SymGetModuleBase64()
+ typedef DWORD64(__stdcall* PFN_SymGetModuleBase64)(IN HANDLE hProcess, IN DWORD64 dwAddr);
+
+ struct DbgHelp
+ {
+ Library dbgLib;
+ PFN_SymInitialize SymInitialize;
+ PFN_SymCleanup SymCleanup;
+ PFN_SymGetLineFromAddr64 SymGetLineFromAddr64;
+ PFN_SymGetSymFromAddr64 SymGetSymFromAddr64;
+ PFN_StackWalk64 StackWalk64;
+ PFN_SymFunctionTableAccess64 SymFunctionTableAccess64;
+ PFN_SymGetModuleBase64 SymGetModuleBase64;
+
+ DbgHelp()
+ : SymInitialize(nullptr)
+ , SymCleanup(nullptr)
+ , SymGetLineFromAddr64(nullptr)
+ , SymGetSymFromAddr64(nullptr)
+ , StackWalk64(nullptr)
+ , SymFunctionTableAccess64(nullptr)
+ , SymGetModuleBase64(nullptr)
+ {
+ }
+
+ bool Load()
+ {
+ if (IsValid())
+ return true;
+
+ if (!dbgLib.Load("dbghelp.dll"))
+ return false;
+
+ SymInitialize = dbgLib.GetProcess("SymInitialize");
+ SymCleanup = dbgLib.GetProcess("SymCleanup");
+ SymGetLineFromAddr64 = dbgLib.GetProcess("SymGetLineFromAddr64");
+ SymGetSymFromAddr64 = dbgLib.GetProcess("SymGetSymFromAddr64");
+ StackWalk64 = dbgLib.GetProcess("StackWalk64");
+ SymFunctionTableAccess64 = dbgLib.GetProcess("SymFunctionTableAccess64");
+ SymGetModuleBase64 = dbgLib.GetProcess("SymGetModuleBase64");
+
+ if (!IsValid())
+ {
+ dbgLib.Free();
+ return false;
+ }
+ return true;
+ }
+
+ bool IsValid() const
+ {
+ return SymInitialize && SymCleanup && SymGetLineFromAddr64 && SymGetSymFromAddr64
+ && StackWalk64 && SymFunctionTableAccess64 && SymGetModuleBase64;
+ }
+ };
+
+ DbgHelp g_DbgHelp;
+ }
+
+ void PrintErrorCode(LPCWSTR lpszFunction)
+ {
+ KGE_ERROR(L"%s failed with HRESULT of %08X", lpszFunction, HRESULT_FROM_WIN32(GetLastError()));
+ }
+
+ void PrintCallStackOnContext(PCONTEXT pContext)
+ {
+ if (!g_DbgHelp.Load())
+ return;
+
+ if (pContext == nullptr)
+ return;
+
+ DWORD dwMachineType;
+ STACKFRAME64 sf;
+ HANDLE hProcess = GetCurrentProcess();
+ HANDLE hThread = GetCurrentThread();
+
+ ZeroMemory(&sf, sizeof(sf));
+
+ sf.AddrPC.Mode = AddrModeFlat;
+ sf.AddrFrame.Mode = AddrModeFlat;
+ sf.AddrStack.Mode = AddrModeFlat;
+ sf.AddrBStore.Mode = AddrModeFlat;
+
+#ifdef _M_IX86
+ dwMachineType = IMAGE_FILE_MACHINE_I386;
+ sf.AddrPC.Offset = pContext->Eip;
+ sf.AddrFrame.Offset = pContext->Ebp;
+ sf.AddrStack.Offset = pContext->Esp;
+#elif _M_X64
+ dwMachineType = IMAGE_FILE_MACHINE_AMD64;
+ sf.AddrPC.Offset = pContext->Rip;
+ sf.AddrFrame.Offset = pContext->Rsp;
+ sf.AddrStack.Offset = pContext->Rsp;
+#elif _M_IA64
+ dwMachineType = IMAGE_FILE_MACHINE_IA64;
+ sf.AddrPC.Offset = pContext->StIIP;
+ sf.AddrFrame.Offset = pContext->IntSp;
+ sf.AddrBStore.Offset = pContext->RsBSP;
+ sf.AddrStack.Offset = pContext->IntSp;
+#else
+#error "Platform not supported!"
+#endif
+
+ constexpr int STACKWALK_MAX_NAMELEN = 1024;
+ BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN];
+
+ KGE_ERROR(L"========== Stack trace ==========");
+
+ while (true)
+ {
+ if (!g_DbgHelp.StackWalk64(dwMachineType, hProcess, hThread, &sf, pContext, NULL,
+ g_DbgHelp.SymFunctionTableAccess64, g_DbgHelp.SymGetModuleBase64, NULL))
+ {
+ PrintErrorCode(L"StackWalk64");
+ break;
+ }
+
+ if (sf.AddrFrame.Offset == 0)
+ {
+ break;
+ }
+
+ ZeroMemory(symbolBuffer, sizeof(symbolBuffer));
+
+ IMAGEHLP_SYMBOL64* pSymbol = reinterpret_cast(symbolBuffer);
+ pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
+ pSymbol->MaxNameLength = STACKWALK_MAX_NAMELEN;
+
+ DWORD64 dwDisplacement;
+ if (!g_DbgHelp.SymGetSymFromAddr64(hProcess, sf.AddrPC.Offset, &dwDisplacement, pSymbol))
+ {
+ PrintErrorCode(L"SymGetSymFromAddr64");
+ break;
+ }
+
+ IMAGEHLP_LINE64 lineInfo;
+ ZeroMemory(&lineInfo, sizeof(IMAGEHLP_LINE64));
+ lineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+
+ DWORD dwLineDisplacement;
+ if (g_DbgHelp.SymGetLineFromAddr64(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo))
+ {
+ String functionName = MultiByteToWide(pSymbol->Name);
+ String fileName = MultiByteToWide(lineInfo.FileName);
+ KGE_ERROR(L"%s (%d): %s", fileName.c_str(), lineInfo.LineNumber, functionName.c_str());
+ }
+ else
+ {
+ String functionName = MultiByteToWide(pSymbol->Name);
+ KGE_ERROR(L"(filename not available): %s", functionName.c_str());
+ }
+
+ if (sf.AddrReturn.Offset == 0)
+ {
+ SetLastError(ERROR_SUCCESS);
+ break;
+ }
+ }
+ }
+
+ void PrintCallStack()
+ {
+ CONTEXT ctx;
+ HANDLE hProcess = GetCurrentProcess();
+
+ if (!g_DbgHelp.Load())
+ return;
+
+ if (!g_DbgHelp.SymInitialize(hProcess, NULL, TRUE))
+ return;
+
+ RtlCaptureContext(&ctx);
+
+ PrintCallStackOnContext(&ctx);
+
+ g_DbgHelp.SymCleanup(hProcess);
+ }
+ }
+}
diff --git a/src/kiwano/platform/win32/helper.h b/src/kiwano/platform/win32/helper.h
index 6091e753..532075bf 100644
--- a/src/kiwano/platform/win32/helper.h
+++ b/src/kiwano/platform/win32/helper.h
@@ -21,22 +21,37 @@
#pragma once
#include
#include
-#include <3rd-party/StackWalker/StackWalker.h>
+#include
namespace kiwano
{
namespace win32
{
+ void PrintCallStack();
+
+ void PrintCallStackOnContext(PCONTEXT pContext);
+
inline void ThrowIfFailed(HRESULT hr)
{
if (FAILED(hr))
{
- StackWalker().ShowCallstack();
+ PrintCallStack();
- static char buffer[1024 + 1];
+ static char buffer[32];
sprintf_s(buffer, "Failed with HRESULT of %08X", hr);
throw std::runtime_error(buffer);
}
}
+
+ inline void WarnIfFailed(HRESULT hr)
+ {
+ if (FAILED(hr))
+ {
+ PrintCallStack();
+
+ KGE_WARN(L"Failed with HRESULT of %08X", hr);
+ }
+ }
+
}
}
diff --git a/src/kiwano/platform/win32/libraries.cpp b/src/kiwano/platform/win32/libraries.cpp
index fd2aca13..d7fb3506 100644
--- a/src/kiwano/platform/win32/libraries.cpp
+++ b/src/kiwano/platform/win32/libraries.cpp
@@ -32,10 +32,10 @@ namespace kiwano
, PathFileExistsW(nullptr)
, SHCreateMemStream(nullptr)
{
- if (shlwapi.Load(L"shlwapi.dll"))
+ if (shlwapi.Load("shlwapi.dll"))
{
- PathFileExistsW = shlwapi.GetProcess(L"PathFileExistsW");
- SHCreateMemStream = shlwapi.GetProcess(L"SHCreateMemStream");
+ PathFileExistsW = shlwapi.GetProcess("PathFileExistsW");
+ SHCreateMemStream = shlwapi.GetProcess("SHCreateMemStream");
}
else
{