Skip to content

Instantly share code, notes, and snippets.

@linnet8989
Last active October 16, 2023 16:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save linnet8989/38b64748cfacdbbc2b5391c7863c6f44 to your computer and use it in GitHub Desktop.
Save linnet8989/38b64748cfacdbbc2b5391c7863c6f44 to your computer and use it in GitHub Desktop.
Tricks of C++ and Windows API
// EnumString - A utility to provide stringizing support for C++ enums
// Author: Francis Xavier Joseph Pulikotil
// Improved by: linnet8989
//
// This code is free software: you can do whatever you want with it,
// although I would appreciate if you gave credit where it's due.
//
// This code is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#ifndef ENUMSTRING_HEADER
#define ENUMSTRING_HEADER
/* Usage example
// EnumString - A utility to provide stringizing support for C++ enums
// Author: Francis Xavier Joseph Pulikotil
//
// This code is free software: you can do whatever you want with it,
// although I would appreciate if you gave credit where it's due.
//
// This code is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#ifndef ENUMSTRING_HEADER
#define ENUMSTRING_HEADER
/* Usage example
// WeekEnd enumeration
#ifndef BEFORE_CPP11
enum class WeekEnd
{
//NotApplicable = 0,
Sunday = 1,
Saturday = 7
};
#else
namespace WeekEnd
{
enum _WeekEnd
{
//NotApplicable = 0,
Sunday = 1,
Saturday = 7
};
}
typedef WeekEnd::_WeekEnd WeekEnd
#endif // !BEFORE_CPP11
// String support for WeekEnd
Begin_Enum_String( WeekEnd )
{
//Enum_String( NotApplicable );
Enum_String( Sunday );
Enum_String( Saturday );
}
End_Enum_String;
// Convert from WeekEnd to string
#ifndef UNRESTRICTED_WITH_ENUMERATION_NAME
const std::string &str = EnumString<WeekEnd>::From( WeekEnd::Saturday );
#else
const std::string &str = EnumString<WeekEnd>::From( Saturday );
#endif // !UNRESTRICTED_WITH_ENUMERATION_NAME
// str should now be "Saturday"
// Convert from string to WeekEnd
WeekEnd w = EnumString<WeekEnd>::To( "Sunday" );
// w should now be Sunday
*/
#include <string>
#include <map>
#include <cassert>
#include "MacroHelper.h" // Optional
// Deprecated, unrestricted code wasn't tested.
// #define UNRESTRICTED_WITH_ENUMERATION_NAME
// Helper macros
#ifndef UNRESTRICTED_WITH_ENUMERATION_NAME
#ifndef BEFORE_CPP11 // using _EnumerationName = EnumerationName;
#define Begin_Enum_String(EnumerationName) \
template <> struct EnumString<EnumerationName> : \
public EnumStringBase< EnumString<EnumerationName>, EnumerationName > \
{ \
using _EnumerationName = EnumerationName; \
static void RegisterEnumerators()
#else // using namespace EnumerationName;
#define Begin_Enum_String(EnumerationName) \
template <> struct EnumString<EnumerationName> : \
public EnumStringBase< EnumString<EnumerationName>, EnumerationName > \
{ \
using namespace EnumerationName; \
static void RegisterEnumerators()
#endif // !BEFORE_CPP11
#else
#define Begin_Enum_String(EnumerationName) \
template <> struct EnumString<EnumerationName> : \
public EnumStringBase< EnumString<EnumerationName>, EnumerationName > \
{ \
static void RegisterEnumerators()
#endif // !UNRESTRICTED_WITH_ENUMERATION_NAME
// {
#if !defined(BEFORE_CPP11) && !defined(UNRESTRICTED_WITH_ENUMERATION_NAME)
#define Enum_String(EnumeratorName) \
RegisterEnumerator( _EnumerationName::EnumeratorName, #EnumeratorName );
#else
#define Enum_String(EnumeratorName) \
RegisterEnumerator( EnumeratorName, #EnumeratorName );
#endif // !BEFORE_CPP11 && !UNRESTRICTED_WITH_ENUMERATION_NAME
// }
#define End_Enum_String \
}
// The EnumString base class
template <class DerivedType, class EnumType>
class EnumStringBase
{
// Types
protected:
typedef std::map<std::string, EnumType> AssocMap;
protected:
// Constructor / Destructor
explicit EnumStringBase();
~EnumStringBase();
private:
// Copy Constructor / Assignment Operator
EnumStringBase(const EnumStringBase &);
const EnumStringBase &operator =(const EnumStringBase &);
// Functions
private:
static AssocMap &GetMap();
protected:
// Use this helper function to register each enumerator
// and its string representation.
static void RegisterEnumerator(const EnumType e, const std::string &eStr);
public:
// Converts from an enumerator to a string.
// Returns an empty string if the enumerator was not registered.
static const std::string &From(const EnumType e);
// Converts from a string to an enumerator.
// Returns the associated enumerator if the conversion is successful; EnumType::NotApplicable otherwise.
static EnumType To(const std::string str);
};
// The EnumString class
// Note: Specialize this class for each enumeration, and implement
// the RegisterEnumerators() function.
template <class EnumType>
struct EnumString : public EnumStringBase< EnumString<EnumType>, EnumType >
{
static void RegisterEnumerators();
};
// Function definitions
template <class D, class E>
typename EnumStringBase<D,E>::AssocMap &EnumStringBase<D,E>::GetMap()
{
// A static map of associations from strings to enumerators
static AssocMap assocMap;
static bool bFirstAccess = true;
// If this is the first time we're accessing the map, then populate it.
if( bFirstAccess )
{
bFirstAccess = false;
D::RegisterEnumerators();
assert( !assocMap.empty() );
}
return assocMap;
}
template <class D, class E>
void EnumStringBase<D,E>::RegisterEnumerator(const E e, const std::string &eStr)
{
const bool bRegistered = GetMap().insert( typename AssocMap::value_type( eStr, e ) ).second;
assert( bRegistered );
(void)sizeof( bRegistered ); // This is to avoid the pesky 'unused variable' warning in Release Builds.
}
template <class D, class E>
const std::string &EnumStringBase<D,E>::From(const E e)
{
for(;;) // Code block
{
// Search for the enumerator in our map
typename AssocMap::const_iterator i;
for(i = GetMap().begin(); i != GetMap().end(); ++i)
if( (*i).second == e )
break;
// If we didn't find it, we can't do this conversion
if( i == GetMap().end() )
break;
// Keep searching and see if we find another one with the same value
typename AssocMap::const_iterator j( i );
for(++j; j != GetMap().end(); ++j)
if( (*j).second == e )
break;
// If we found another one with the same value, we can't do this conversion
if( j != GetMap().end() )
break;
// We found exactly one string which matches the required enumerator
return (*i).first;
}
// We couldn't do this conversion; return an empty string.
static const std::string dummy;
return dummy;
}
template <class D, class E>
E EnumStringBase<D,E>::To(const std::string str)
{
// Search for the string in our map.
const typename AssocMap::const_iterator itr( GetMap().find( str ) );
// If we have it, then return the associated enumerator.
if( itr != GetMap().end() )
{
return (*itr).second;
}
// We don't have it; the conversion failed.
#if !defined(BEFORE_CPP11) && !defined(UNRESTRICTED_WITH_ENUMERATION_NAME)
return E::NotApplicable;
#else
return NotApplicable;
#endif // !BEFORE_CPP11 && !UNRESTRICTED_WITH_ENUMERATION_NAME
//return GetMap()[str];
}
#endif
// WeekEnd enumeration
#ifndef BEFORE_CPP11
enum class WeekEnd
{
//NotApplicable = 0,
Sunday = 1,
Saturday = 7
};
#else
namespace WeekEnd
{
enum _WeekEnd
{
//NotApplicable = 0,
Sunday = 1,
Saturday = 7
};
}
typedef WeekEnd::_WeekEnd WeekEnd
#endif // !BEFORE_CPP11
// String support for WeekEnd
Begin_Enum_String( WeekEnd )
{
//Enum_String( NotApplicable );
Enum_String( Sunday );
Enum_String( Saturday );
}
End_Enum_String;
// Convert from WeekEnd to string
#ifndef UNRESTRICTED_WITH_ENUMERATION_NAME
const std::string &str = EnumString<WeekEnd>::From( WeekEnd::Saturday );
#else
const std::string &str = EnumString<WeekEnd>::From( Saturday );
#endif // !UNRESTRICTED_WITH_ENUMERATION_NAME
// str should now be "Saturday"
// Convert from string to WeekEnd
WeekEnd w = EnumString<WeekEnd>::To( "Sunday" );
// w should now be Sunday
*/
#include <string>
#include <map>
#include <cassert>
// Deprecated, unrestricted code wasn't tested.
// #define UNRESTRICTED_WITH_ENUMERATION_NAME
// Helper macros
#ifndef UNRESTRICTED_WITH_ENUMERATION_NAME
#ifndef BEFORE_CPP11 // using _EnumerationName = EnumerationName;
#define Begin_Enum_String(EnumerationName) \
template <> struct EnumString<EnumerationName> : \
public EnumStringBase< EnumString<EnumerationName>, EnumerationName > \
{ \
using _EnumerationName = EnumerationName; \
static void RegisterEnumerators()
#else // using namespace EnumerationName;
#define Begin_Enum_String(EnumerationName) \
template <> struct EnumString<EnumerationName> : \
public EnumStringBase< EnumString<EnumerationName>, EnumerationName > \
{ \
using namespace EnumerationName; \
static void RegisterEnumerators()
#endif // !BEFORE_CPP11
#else
#define Begin_Enum_String(EnumerationName) \
template <> struct EnumString<EnumerationName> : \
public EnumStringBase< EnumString<EnumerationName>, EnumerationName > \
{ \
static void RegisterEnumerators()
#endif // !UNRESTRICTED_WITH_ENUMERATION_NAME
// {
#if !defined(BEFORE_CPP11) && !defined(UNRESTRICTED_WITH_ENUMERATION_NAME)
#define Enum_String(EnumeratorName) \
RegisterEnumerator( _EnumerationName::EnumeratorName, #EnumeratorName );
#else
#define Enum_String(EnumeratorName) \
RegisterEnumerator( EnumeratorName, #EnumeratorName );
#endif // !BEFORE_CPP11 && !UNRESTRICTED_WITH_ENUMERATION_NAME
// }
#define End_Enum_String \
}
// The EnumString base class
template <class DerivedType, class EnumType>
class EnumStringBase
{
// Types
protected:
typedef std::map<std::string, EnumType> AssocMap;
protected:
// Constructor / Destructor
explicit EnumStringBase();
~EnumStringBase();
private:
// Copy Constructor / Assignment Operator
EnumStringBase(const EnumStringBase &);
const EnumStringBase &operator =(const EnumStringBase &);
// Functions
private:
static AssocMap &GetMap();
protected:
// Use this helper function to register each enumerator
// and its string representation.
static void RegisterEnumerator(const EnumType e, const std::string &eStr);
public:
// Converts from an enumerator to a string.
// Returns an empty string if the enumerator was not registered.
static const std::string &From(const EnumType e);
// Converts from a string to an enumerator.
// Returns the associated enumerator if the conversion is successful; EnumType::NotApplicable otherwise.
static EnumType To(const std::string str);
};
// The EnumString class
// Note: Specialize this class for each enumeration, and implement
// the RegisterEnumerators() function.
template <class EnumType>
struct EnumString : public EnumStringBase< EnumString<EnumType>, EnumType >
{
static void RegisterEnumerators();
};
// Function definitions
template <class D, class E>
typename EnumStringBase<D,E>::AssocMap &EnumStringBase<D,E>::GetMap()
{
// A static map of associations from strings to enumerators
static AssocMap assocMap;
static bool bFirstAccess = true;
// If this is the first time we're accessing the map, then populate it.
if( bFirstAccess )
{
bFirstAccess = false;
D::RegisterEnumerators();
assert( !assocMap.empty() );
}
return assocMap;
}
template <class D, class E>
void EnumStringBase<D,E>::RegisterEnumerator(const E e, const std::string &eStr)
{
const bool bRegistered = GetMap().insert( typename AssocMap::value_type( eStr, e ) ).second;
assert( bRegistered );
(void)sizeof( bRegistered ); // This is to avoid the pesky 'unused variable' warning in Release Builds.
}
template <class D, class E>
const std::string &EnumStringBase<D,E>::From(const E e)
{
for(;;) // Code block
{
// Search for the enumerator in our map
typename AssocMap::const_iterator i;
for(i = GetMap().begin(); i != GetMap().end(); ++i)
if( (*i).second == e )
break;
// If we didn't find it, we can't do this conversion
if( i == GetMap().end() )
break;
// Keep searching and see if we find another one with the same value
typename AssocMap::const_iterator j( i );
for(++j; j != GetMap().end(); ++j)
if( (*j).second == e )
break;
// If we found another one with the same value, we can't do this conversion
if( j != GetMap().end() )
break;
// We found exactly one string which matches the required enumerator
return (*i).first;
}
// We couldn't do this conversion; return an empty string.
static const std::string dummy;
return dummy;
}
template <class D, class E>
E EnumStringBase<D,E>::To(const std::string str)
{
//// Search for the string in our map.
//const typename AssocMap::const_iterator itr( GetMap().find( str ) );
//// If we have it, then return the associated enumerator.
//if( itr != GetMap().end() )
//{
// return (*itr).second;
//}
//// We don't have it; the conversion failed.
#if !defined(BEFORE_CPP11) && !defined(UNRESTRICTED_WITH_ENUMERATION_NAME)
//return E::NotApplicable;
#else
//return NotApplicable;
#endif // !BEFORE_CPP11 && !UNRESTRICTED_WITH_ENUMERATION_NAME
return GetMap()[str];
}
#endif
#pragma once
#include <stdio.h>
#ifdef _UNICODE
#define strlenof(a) wcslen(a)
#define strsizeof(a) (wcslen(a) + 1)
#else
#define strlenof(a) strlen(a)
#define strsizeof(a) (strlen(a) + 1)
#endif // _UNICODE
#define arrsizeof(a) (sizeof(a) / sizeof(a[0]))#pragma once
#include <stdio.h>
#include <stddef.h>
#if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
#define CPP11_AND_AFTER
#else
#define BEFORE_CPP11
#endif
#ifdef _UNICODE
#define strlenof(a) wcslen(a)
#define strsizeof(a) (wcslen(a) + 1)
#else
#define strlenof(a) strlen(a)
#define strsizeof(a) (strlen(a) + 1)
#endif // _UNICODE
#define arrsizeof(a) (sizeof(a) / sizeof(*a))
#define arrlenof(a) (arrsizeof(a) - 1)
#define SET_THIS(x) this->x = x;
#define RESET_THIS(x) this->x = obj.x;
#define PTR_ADD(p1, p2) ((uintptr_t)(p1) + (uintptr_t)(p2))
#define PTR_SUB(p1, p2) ((ptrdiff_t)((uintptr_t)(p1) - (uintptr_t)(p2)))
#define ADDR_ADD_OFFSET(Address, Offset) ((ULONG_PTR)(Address) + (ULONG_PTR)(Offset))
#define ADDR_SUB_OFFSET(Address, Offset) ((ULONG_PTR)(Address) - (ULONG_PTR)(Offset))
#define ALIGN_UP_BY(Address, Align) (((ULONG_PTR)(Address) + (Align) - 1) & ~((Align) - 1))
#define ALIGN_UP(Address, Type) ALIGN_UP_BY(Address, sizeof(Type))
#define PTR_MOVE_OF(Pointer, Offset, Type) {Pointer = ((Type)ADDR_ADD_OFFSET(Pointer, Offset));}
#ifdef CPP11_AND_AFTER
#define PTR_ADD_OFFSET(Pointer, Offset) (decltype(Pointer)ADDR_ADD_OFFSET(Pointer, Offset))
#define PTR_SUB_OFFSET(Pointer, Offset) (decltype(Pointer)ADDR_SUB_OFFSET(Pointer, Offset))
#define ALIGN_UP_POINTER_BY(Pointer, Align) (decltype(Pointer)ALIGN_UP_BY(Pointer, Align))
#define ALIGN_UP_POINTER(Pointer, Type) (decltype(Pointer)ALIGN_UP(Pointer, Type))
#define PTR_MOVE(Pointer, Offset) PTR_MOVE_OF(Pointer, Offset, decltype(Pointer))
#else
#define PTR_ADD_OFFSET(Pointer, Offset) ((PVOID)ADDR_ADD_OFFSET(Pointer, Offset))
#define PTR_SUB_OFFSET(Pointer, Offset) ((PVOID)ADDR_SUB_OFFSET(Pointer, Offset))
#define ALIGN_UP_POINTER_BY(Pointer, Align) ((PVOID)ALIGN_UP_BY(Pointer, Align))
#define ALIGN_UP_POINTER(Pointer, Type) ((PVOID)ALIGN_UP(Pointer, Type))
#define PTR_MOVE(Pointer, Offset) PTR_MOVE_OF(Pointer, Offset, PVOID)
#endif
#define MAX(a, b) (a < b ? b : a)
#define MIN(a, b) (a < b ? a : b)
#define CEIL_DIVIDE(dividend, divisor) (dividend % divisor == 0 ? dividend / divisor : dividend / divisor + 1)
#define arrlenof(a) (arrsizeof(a) - 1)
#define SET_THIS(x) this->x = x;
#define TEST_POINTER(type, addr, offset) ((type)((int)addr + offset))
#define MOVE_POINTER(type, addr, offset) addr = (type)((int)addr + offset);
#pragma once
#include <string.h>
#include <string>
#include <vector>
#include <sstream>
int ReadLineA(char szBuf[], const int size, FILE * stream = stdin)
{
int count = 0, ch = 0;#pragma once
#include <string.h>
#include <string>
#include <vector>
#include <sstream>
int ReadLineA(char szBuf[], const int size, FILE * stream = stdin)
{
int count = 0, ch = 0;
for (; count + 1 < size && (ch = getc(stream)) != '\n'; count++)
{
if (ch == EOF) return EOF;
szBuf[count] = ch;
}
if (count + 1 >= size && size >= 0 && stream == stdin)
{
while ((ch = getchar()) != '\n' && ch != EOF);
}
return count;
}
#define ReadLine ReadLineA
namespace std
{
vector<string> split_whitespace(string str)
{
vector<string> result;
istringstream ss(str);
while (ss >> str)
{
result.push_back(str);
}
return result;
}
vector<string> split(string str, string pattern, size_t maxsplits = -1, bool includeEmpty = false)
{
vector<string> result;
string::size_type pos;
str += pattern;//��չ�ַ����Է������
int size = str.size();
int patternLength = pattern.size() - 1;
for (int i = 0; i < size; i++)
{
pos = str.find(pattern, i);
if (pos < size)
{
string s = str.substr(i, pos - i);
if (!s.empty() || includeEmpty)
{
if (result.size() >= maxsplits)
{
result.push_back(str.substr(i));
return result;
}
result.push_back(s);
}
i = pos + patternLength;
}
}
return result;
}
string trim(const string str)
{
string::size_type pos = str.find_first_not_of(' ');
if (pos == string::npos)
{
return str;
}
string::size_type pos2 = str.find_last_not_of(' ');
if (pos2 != string::npos)
{
return str.substr(pos, pos2 - pos + 1);
}
return str.substr(pos);
}
}
char *stptok(
const char *s,/* string to parse */
char *tok, /* buffer that receives the "token" that gets scanned */
size_t toklen,/* length of the buffer */
const char *brk /* string of break characters that will stop the scan */)
{
char *lim; /* limit of token */
const char *b; /* current break character */
/* check for invalid pointers */
if (!s || !tok || !brk)
return NULL;
/* check for empty string */
if (!*s)
return NULL;
lim = tok + toklen - 1;
while (*s && tok < lim)
{
for (b = brk; *b; b++)
{
if (*s == *b)
{
*tok = 0;
for (++s, b = brk; *s && *b; ++b)
{
if (*s == *b)
{
++s;
b = brk;
}
}
if (!*s)
return NULL;
return (char *)s;
}
}
*tok++ = *s++;
}
*tok = 0;
if (!*s)
return NULL;
return (char *)s;
}
for (; count + 1 < size && (ch = getc(stream)) != '\n'; count++)
{
if (ch == EOF) return EOF;
szBuf[count] = ch;
}
if (count + 1 >= size && size >= 0 && stream == stdin)
{
while ((ch = getchar()) != '\n' && ch != EOF);
}
return count;
}
#define ReadLine ReadLineA
namespace std
{
vector<string> split_whitespace(string str)
{
vector<string> result;
istringstream ss(str);
while (ss >> str)
{
result.push_back(str);
}
return result;
}
vector<string> split(string str, string pattern, size_t maxsplits = -1, bool includeEmpty = false)
{
vector<string> result;
string::size_type pos;
str += pattern;//扩展字符串以方便操作
int size = str.size();
int patternLength = pattern.size() - 1;
for (int i = 0; i < size; i++)
{
pos = str.find(pattern, i);
if (pos < size)
{
string s = str.substr(i, pos - i);
if (!s.empty() || includeEmpty)
{
if (result.size() >= maxsplits)
{
result.push_back(str.substr(i));
return result;
}
result.push_back(s);
}
i = pos + patternLength;
}
}
return result;
}
string trim(const string str)
{
string::size_type pos = str.find_first_not_of(' ');
if (pos == string::npos)
{
return str;
}
string::size_type pos2 = str.find_last_not_of(' ');
if (pos2 != string::npos)
{
return str.substr(pos, pos2 - pos + 1);
}
return str.substr(pos);
}
}
char *stptok(
const char *s,/* string to parse */
char *tok, /* buffer that receives the "token" that gets scanned */
size_t toklen,/* length of the buffer */
const char *brk /* string of break characters that will stop the scan */)
{
char *lim; /* limit of token */
const char *b; /* current break character */
/* check for invalid pointers */
if (!s || !tok || !brk)
return NULL;
/* check for empty string */
if (!*s)
return NULL;
lim = tok + toklen - 1;
while (*s && tok < lim)
{
for (b = brk; *b; b++)
{
if (*s == *b)
{
*tok = 0;
for (++s, b = brk; *s && *b; ++b)
{
if (*s == *b)
{
++s;
b = brk;
}
}
if (!*s)
return NULL;
return (char *)s;
}
}
*tok++ = *s++;
}
*tok = 0;
if (!*s)
return NULL;
return (char *)s;
}
#pragma once
#include "windows.h"
BOOL ReadProcessMemoryEx(
HANDLE hProcess,
LPCVOID lpBaseAddress,
LPVOID lpBuffer,
SIZE_T nSize,
SIZE_T * lpNumberOfBytesRead)
{
// 考虑跨页读问题, 要读多次.
// e.g. 跨多页的问题
// e.g. 从0x00401234 读 0x12345个字符到缓冲区
BOOL bRc = FALSE;
DWORD dwPos = 0;
DWORD dwRd = 0;
DWORD dwRdBack = 0;
const DWORD dwPageCb = 0x1000; ///< 一页内存的size
DWORD dwRemainder = 0;
if (NULL != lpNumberOfBytesRead)
{
*lpNumberOfBytesRead = 0;
}
// 读第一部分, 不对齐页的部分, 比一页小, 只读一次
dwRemainder = dwPageCb - ((DWORD)lpBaseAddress % dwPageCb);
if (nSize <= dwRemainder)
{
// 在页中间读的, 读的数据长度不到页尾, 一次读完返回
bRc = ReadProcessMemory(#pragma once
#include "windows.h"
#include <Psapi.h>
BOOL ReadProcessMemoryEx(
HANDLE hProcess,
LPCVOID lpBaseAddress,
LPVOID lpBuffer,
SIZE_T nSize,
SIZE_T * lpNumberOfBytesRead)
{
// ���ǿ�ҳ������, Ҫ�����.
// e.g. ���ҳ������
// e.g. ��0x00401234 �� 0x12345���ַ���������
BOOL bRc = FALSE;
DWORD dwPos = 0;
DWORD dwRd = 0;
DWORD dwRdBack = 0;
const DWORD dwPageCb = 0x1000; ///< һҳ�ڴ��size
DWORD dwRemainder = 0;
if (NULL != lpNumberOfBytesRead)
{
*lpNumberOfBytesRead = 0;
}
// ����һ����, ������ҳ�IJ���, ��һҳС, ֻ��һ��
dwRemainder = dwPageCb - ((DWORD)lpBaseAddress % dwPageCb);
if (nSize <= dwRemainder)
{
// ��ҳ�м����, �������ݳ��Ȳ���ҳβ, һ�ζ��귵��
bRc = ReadProcessMemory(
hProcess,
(void*)((DWORD)lpBaseAddress + dwPos),
(void*)((DWORD)lpBuffer + dwPos),
nSize,
&dwRdBack);
if (NULL != lpNumberOfBytesRead)
{
*lpNumberOfBytesRead += dwRdBack;
}
if ((!bRc) || (dwRdBack != nSize))
{
return FALSE;
}
return bRc;
}
// Ҫ�������ݳ���ҳ�߽��
if (dwRemainder > 0)
{
nSize -= dwRemainder;
bRc = ReadProcessMemory(
hProcess,
(void*)((DWORD)lpBaseAddress + dwPos),
(void*)((DWORD)lpBuffer + dwPos),
dwRemainder,
&dwRdBack);
if (NULL != lpNumberOfBytesRead)
{
*lpNumberOfBytesRead += dwRdBack;
}
if ((!bRc) || (dwRdBack != dwRemainder))
{
return FALSE;
}
dwPos += dwRdBack;
}
// �ظ�����2����, ��ҳ�Ķ�
while (nSize >= dwPageCb)
{
nSize -= dwPageCb;
bRc = ReadProcessMemory(
hProcess,
(void*)((DWORD)lpBaseAddress + dwPos),
(void*)((DWORD)lpBuffer + dwPos),
dwPageCb,
&dwRdBack);
if (NULL != lpNumberOfBytesRead)
{
*lpNumberOfBytesRead += dwRdBack;
}
if ((!bRc) || (dwRdBack != dwPageCb))
{
return FALSE;
}
dwPos += dwRdBack;
}
// ��β�Ͳ���, ��һҳС, ֻ��һ�ξ͹���
if (nSize > 0)
{
bRc = ReadProcessMemory(
hProcess,
(void*)((DWORD)lpBaseAddress + dwPos),
(void*)((DWORD)lpBuffer + dwPos),
nSize,
&dwRdBack);
if (NULL != lpNumberOfBytesRead)
{
*lpNumberOfBytesRead += dwRdBack;
}
if ((!bRc) || (dwRdBack != nSize))
{
return FALSE;
}
}
return TRUE;
}
#define BUFSIZE 512
string GetFileNameFromHandle(HANDLE hFile)
{
BOOL bSuccess = FALSE;
TCHAR pszFilename[MAX_PATH + 1];
HANDLE hFileMap;
// Get the file size.
DWORD dwFileSizeHi = 0;
DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi);
if (dwFileSizeLo == 0 && dwFileSizeHi == 0)
{
_tprintf(TEXT("Cannot map a file with a length of zero.\n"));
return "";
}
// Create a file mapping object.
hFileMap = CreateFileMapping(hFile,
NULL,
PAGE_READONLY,
0,
1,
NULL);
if (hFileMap)
{
// Create a file mapping to get the file name.
void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);
if (pMem)
{
if (GetMappedFileName(GetCurrentProcess(),
pMem,
pszFilename,
MAX_PATH))
{
// Translate path with device name to drive letters.
TCHAR szTemp[BUFSIZE];
szTemp[0] = '\0';
if (GetLogicalDriveStrings(BUFSIZE - 1, szTemp))
{
TCHAR szName[MAX_PATH];
TCHAR szDrive[3] = TEXT(" :");
BOOL bFound = FALSE;
TCHAR* p = szTemp;
do
{
// Copy the drive letter to the template string
*szDrive = *p;
// Look up each device name
if (QueryDosDevice(szDrive, szName, MAX_PATH))
{
size_t uNameLen = _tcslen(szName);
if (uNameLen < MAX_PATH)
{
bFound = _tcsnicmp(pszFilename, szName, uNameLen) == 0
&& *(pszFilename + uNameLen) == _T('\\');
if (bFound)
{
// Reconstruct pszFilename using szTempFile
// Replace device path with DOS path
TCHAR szTempFile[MAX_PATH];
StringCchPrintf(szTempFile,
MAX_PATH,
TEXT("%s%s"),
szDrive,
pszFilename + uNameLen);
StringCchCopyN(pszFilename, MAX_PATH + 1, szTempFile, _tcslen(szTempFile));
}
}
}
// Go to the next NULL character.
while (*p++);
} while (!bFound && *p); // end of string
}
}
bSuccess = TRUE;
UnmapViewOfFile(pMem);
}
CloseHandle(hFileMap);
}
//_tprintf(TEXT("File name is %s\n"), pszFilename);
return(pszFilename);
}
hProcess,
(void*)((DWORD)lpBaseAddress + dwPos),
(void*)((DWORD)lpBuffer + dwPos),
nSize,
&dwRdBack);
if (NULL != lpNumberOfBytesRead)
{
*lpNumberOfBytesRead += dwRdBack;
}
if ((!bRc) || (dwRdBack != nSize))
{
return FALSE;
}
return bRc;
}
// 要读的数据超过页边界的
if (dwRemainder > 0)
{
nSize -= dwRemainder;
bRc = ReadProcessMemory(
hProcess,
(void*)((DWORD)lpBaseAddress + dwPos),
(void*)((DWORD)lpBuffer + dwPos),
dwRemainder,
&dwRdBack);
if (NULL != lpNumberOfBytesRead)
{
*lpNumberOfBytesRead += dwRdBack;
}
if ((!bRc) || (dwRdBack != dwRemainder))
{
return FALSE;
}
dwPos += dwRdBack;
}
// 重复读第2部分, 整页的读
while (nSize >= dwPageCb)
{
nSize -= dwPageCb;
bRc = ReadProcessMemory(
hProcess,
(void*)((DWORD)lpBaseAddress + dwPos),
(void*)((DWORD)lpBuffer + dwPos),
dwPageCb,
&dwRdBack);
if (NULL != lpNumberOfBytesRead)
{
*lpNumberOfBytesRead += dwRdBack;
}
if ((!bRc) || (dwRdBack != dwPageCb))
{
return FALSE;
}
dwPos += dwRdBack;
}
// 读尾巴部分, 比一页小, 只读一次就够了
if (nSize > 0)
{
bRc = ReadProcessMemory(
hProcess,
(void*)((DWORD)lpBaseAddress + dwPos),
(void*)((DWORD)lpBuffer + dwPos),
nSize,
&dwRdBack);
if (NULL != lpNumberOfBytesRead)
{
*lpNumberOfBytesRead += dwRdBack;
}
if ((!bRc) || (dwRdBack != nSize))
{
return FALSE;
}
}
return TRUE;
}
@Pravila00
Copy link

@linnet8989 would you be okay if I create a proper GitHub repository for this code and then package it into Vcpkg? I believe it could be useful to spread this code among folks through Vcpkg :).

If you want to create the GitHub repository that fine with me as well!

@linnet8989
Copy link
Author

@linnet8989 would you be okay if I create a proper GitHub repository for this code and then package it into Vcpkg? I believe it could be useful to spread this code among folks through Vcpkg :).

If you want to create the GitHub repository that fine with me as well!

WTFPL
140px-WTFPL_logo svg

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment