Keep a string value in memory after "FreeLibrary" - c++

I do have a simple test-case here (C++) which does LoadLibrary, GetProcAddress & calls the function (ProcAdd).
The signature is "char* ProcAdd(char*)".
Now I do get the string correctly in the executable, but once I do "FreeLibrary", it's gone... (obviously because I just did a return "hello").
The thing is, that I have another dll (.NET, C#) where the signature is "[return: MarshalAs LPSTR]string ProcAdd([MarshalAs LPSTR] string)".
Now this function ALSO returns a string, but when I do "FreeLibrary", the string is still accessible within my executable?!
How does that come, and how could I mimic the same behaviour?
(and yes, I know I can store it in another variable, but I would like to understand what is happening and how I can reproduce this .NET behaviour).
Thanks a lot!
As requested the code:
C++ exe:
int main( void )
{
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
void * val = NULL;
// Get a handle to the DLL module.
// hinstLib = LoadLibrary(TEXT("C:\\Users\\steven\\temp\\myMyMy.orig.dll"));
hinstLib = LoadLibrary(TEXT("C:\\Users\\steven\\temp\\myMyMy.proxy.dll"));
// If the handle is valid, try to get the function address.
if (hinstLib != NULL)
{
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "ProcAdd");
// If the function address is valid, call the function.
if (NULL != ProcAdd)
{
fRunTimeLinkSuccess = TRUE;
val = (ProcAdd) ("0987654321");
}
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
// If unable to call the DLL function, use an alternative.
if (! fRunTimeLinkSuccess)
printf("Message printed from executable\n");
return 0;
}
C++ dll:
#include <Windows.h>
#include <iostream>
#include <fstream>
static const char tmp[] = "hello";
extern "C" const char * __stdcall ProcAdd(const char * param1) {
FILE * fp = fopen("C:\\tmp\\ProcAdd.txt", "a");
if ( fp ) {
fprintf(fp, "param1: '%s'\r\n", param1);
fclose(fp);
}
// return strdup("hello");
// return "hello";
return tmp;
}
C# dll:
[return: MarshalAs(UnmanagedType.LPStr)]
public static string ProcAdd([MarshalAs(UnmanagedType.LPStr)] string param1)
{
string str;
try
{
str = new WebClient().DownloadString("http://www.salvania.be/test.php?param1=" + param1);
}
catch (Exception exception1)
{
str = "Error-DLL";
}
return str;
}
Working return:
// http://stackoverflow.com/questions/14406818/heapcreate-and-heapalloc-confuse
HANDLE winHandle = HeapCreate( 0, sizeof(tmp), sizeof(tmp) );
char* s = (char*)HeapAlloc( winHandle, 0, sizeof(tmp) + 1 );
strcpy((char*)s, tmp);
s[sizeof(tmp)] = 0;

If you just return "hello", that hello string may come from the data segment of the shared library, and may be unloaded after the life-time of the library.
To ensure the returned string live after the life-time of the library, you may store it on heap or otherwise provide a buffer from the caller.

Related

Why can I pass CHAR[] as a LPSTR parameter?

This is working for me...
std::string GetProgramDataPath() {
CHAR path[MAX_PATH];
HRESULT hr = SHGetFolderPathA(nullptr, CSIDL_COMMON_APPDATA, nullptr, 0, path); // path accepted as LPSTR parameter?
if (SUCCEEDED(hr)) {
return std::string(path); // then automatically cast to const char*?
}
else {
return std::string();
}
}
...but I don't know why. I try to pass LPSTR, but I get:
Error C4700 "uninitialized local variable 'path' used"
I look up how to initialize LPSTR and come up with this:
std::string GetProgramDataPath() {
LPSTR path = new CHAR[MAX_PATH];
HRESULT hr = SHGetFolderPathA(nullptr, CSIDL_COMMON_APPDATA, nullptr, 0, path);
if (SUCCEEDED(hr)) {
std::string strPath(path);
delete[] path;
return std::string(strPath);
}
else {
delete[] path;
return std::string();
}
}
Is this the 'correct' code? With new and delete it seems wrong. Am I doing something unsafe by just using CHAR[]? How come it works instead of LPSTR? I believe it has something to do with the "equivalence of pointers and arrays" in C, but it seems there are some automatic conversions from CHAR[] to LPSTR to const char * in this code I don't understand.
Instead of managing the memory your self with new and delete I'd use a std::string instead and let it manage the memory.
static std::string GetProgramDataPath()
{
std::string buffer(MAX_PATH, '\0');
const HRESULT result = SHGetFolderPathA
(
nullptr,
CSIDL_COMMON_APPDATA,
nullptr,
0,
buffer.data()
);
if (SUCCEEDED(result))
{
// Cut off the trailing null terminating characters.
// Doing this will allow you to append to the string
// in the position that you'd expect.
if (const auto pos{ buffer.find_first_of('\0') }; pos != std::string::npos)
buffer.resize(pos);
// Here is how you can append to the string further.
buffer.append(R"(\Some\Other\Directory)");
return buffer;
}
buffer.clear();
return buffer;
}
Here is one way you could do it using std::filesystem::path and SHGetKnownFolderPath.
namespace fs = std::filesystem;
static fs::path GetProgramDataPath()
{
struct buffer {
wchar_t* data{ nullptr };
~buffer() { CoTaskMemFree(data); }
} buf{};
const HRESULT result = SHGetKnownFolderPath
(
FOLDERID_ProgramData,
0,
nullptr,
&buf.data
);
return SUCCEEDED(result)
? fs::path{ buf.data }
: fs::path{};
}
int main()
{
fs::path path{ GetProgramDataPath() };
if (!path.empty())
{
// Here is one way you can append to a path.
// You can also use the append member function as well.
path /= R"(Some\Other\Directory)";
// When you're ready you can call either the generic_string or
// string member function on the path.
const std::string s1{ path.string() };
const std::string s2{ path.generic_string() };
// Prints: 'C:\ProgramData\Some\Other\Directory'.
std::cout << s1 << '\n';
// Prints: 'C:/ProgramData/Some/Other/Directory'.
std::cout << s2 << '\n';
}
}
This is working for me...but I don't know why.
LPSTR is just an alias for CHAR* (aka char*):
typedef CHAR *LPSTR;
In certain contexts, a fixed-sized CHAR[] (aka char[]) array will decay into a CHAR* (aka char*) pointer to its 1st element, such as when passing the array by value in a function parameter, as you are doing.
I try to pass LPSTR, but I get Error C4700 "uninitialized local variable 'path' used".
Because LPSTR is just a pointer, and you likely did not point it at anything meaningful.
Is this the 'correct' code?
Technically yes, that will work (though return std::string(strPath) should be return strPath instead). However, you should consider using std::string or std::vector<char> instead to manage memory for you, don't use new[]/delete[] directly, eg:
std::string GetProgramDataPath() {
std::vector<char> path(MAX_PATH);
HRESULT hr = SHGetFolderPathA(nullptr, CSIDL_COMMON_APPDATA, nullptr, 0, path.data());
if (SUCCEEDED(hr)) {
return std::string(path.data());
}
return std::string();
}
Am I doing something unsafe by just using CHAR[]?
No.
How come it works instead of LPSTR?
Because CHAR[] decays into the same type that LPSTR is an alias of.
it seems there are some automatic conversions from CHAR[] to LPSTR to const char * in this code.
Correct.

Can't read complete string when writing into IPC SHM in c++

I'm attempting to build a simple interface to use shm ipc in c++. For that, I've written the following code:
sharedmem.h:
#pragma once
#include <iostream>
#include <sstream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
using namespace std;
namespace IPC
{
void Send(const string filename, std::string msg,int size=1024 )
{
key_t key = ftok(filename.c_str(),65);
std::stringstream ss;
ss << msg.c_str();
int shmid = shmget(key,size,0666|IPC_CREAT);
char *str = (char*) shmat(shmid,(void*)0,0);
ss >> str;
shmdt(str);
}
string Receive(const string filename, int size=1024 )
{
key_t key = ftok(filename.c_str(),65);
int shmid = shmget(key,size,0666|IPC_CREAT);
char *str = (char*) shmat(shmid,(void*)0,0);
string ret(str);
shmdt(str);
shmctl(shmid,IPC_RMID,NULL);
return ret;
}
};
Outside, I use it like:
sender.cpp
#include "sharedmem.h"
int main()
{
IPC::Send("fila1", "hello ipc");
return 0;
}
receiver.cpp
#include "sharedmem.h"
int main()
{
std::string ret = IPC::Receive("fila1");
cout << "Recebi na fila: " << ret;
return 0;
}
CMakeLists.txt:
set (CMAKE_CXX_STANDARD 17)
add_executable(sender sender.cpp)
add_executable(receiver receiver.cpp)
and built with cmake . && make
In this example I write "hello ipc" but the other process reads only "hello". What could be wrong here? Thanks in advance.
In your send function:
void Send(const string filename, std::string msg,int size=1024 )
{
key_t key = ftok(filename.c_str(),65);
std::stringstream ss;
ss << msg.c_str();
int shmid = shmget(key,size,0666|IPC_CREAT); // this call could fail, what happens next is
// a likely a segmentation error.
// ... or worse.
char *str = (char*) shmat(shmid,(void*)0,0);
ss >> str; // <-- error is here. You extract from ss until the first whitespace character.
// what happens if input string is larger than the size of the allocated block?
shmdt(str);
}
The stringstream ss has no functional use in your function, except for adding a bug. I suggest you try this instead:
int Send(const string& filename, const std::string& msg) noexcept // if you have no return value,
// you should throw on error,
// let's avoid that
{
key_t key = ftok(filename.c_str(), 65); // you should maybe consider using a named constant
// for your project ID
if (key == -1)
return errno;
int shmid = shmget(key, msg.length() + 1, 0666 | IPC_CREAT); // allocate enough memory for the
// message, plus its NULL terminator
if (shmid == -1)
return errno;
void *shared_mem = shmat(shmid, nullptr, 0);
if (shared_mem == (void*)-1)
{
// the systeml failed to lock the allocated memory.
// do some cleanup by de-allocating the shared memory block.
int ret = errno; // keep original error for return.
shmctl(shmid , IPC_RMID, nullptr);
return ret;
}
// copy message string with its NULL terminator to shared memory
memcpy(shared_mem, msg.c_str(), msg.length() + 1); // using length() + 1 is ok here, result of
// c_str() always has a NULL terminator.
shmdt(shared_mem);
return 0;
}
Your receive function also lacks in error checking. That should be very similar to the Send() function.
Note that the strings are passed by const reference, that's to avoid copying them (and the potential errors associated with those unneeded memory allocations)

Allocating memory in specific Windows DLL module

I want to allocate some memory inside a specific module of a process instead of the process in general. The following Windows C++ code can allocate memory inside a process given its process id:
#include "pch.h"
#include <windows.h>
#include <winternl.h>
#include <processthreadsapi.h>
#include <iostream>
#include <conio.h>
#pragma comment(lib, "ntdll.lib")
typedef NTSTATUS (NTAPI *nt_alloc_virtual_memory_func)(HANDLE process_handle, PVOID* base_address, ULONG_PTR zero_bits,
PSIZE_T region_size, ULONG allocation_type, ULONG protect);
typedef NTSTATUS (NTAPI *nt_free_virtual_memory_func)(HANDLE process_handle, PVOID* base_address, PSIZE_T region_size,
ULONG free_type);
void enable_allocating_executable_memory()
{
PROCESS_MITIGATION_DYNAMIC_CODE_POLICY mp;
ZeroMemory(&mp, sizeof mp);
mp.ProhibitDynamicCode = FALSE;
SetProcessMitigationPolicy(ProcessDynamicCodePolicy, &mp, sizeof mp);
}
long allocate_memory(char** arguments, const HANDLE process_handle, PVOID process_memory, SIZE_T& allocation_size)
{
const auto memory_size = arguments[3];
allocation_size = strtoul(memory_size, nullptr, 10);
const auto nt_allocate_virtual_memory = reinterpret_cast<nt_alloc_virtual_memory_func>(GetProcAddress(
GetModuleHandle(L"ntdll.dll"), "NtAllocateVirtualMemory"));
const auto allocation_status = nt_allocate_virtual_memory(process_handle, &process_memory, 0, &allocation_size,
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (NT_SUCCESS(allocation_status))
{
std::cout << std::hex << process_memory << std::endl;
}
return allocation_status;
}
int free_memory(const int argument_count, char** arguments,
const HANDLE process_handle, SIZE_T& mem_size)
{
const auto address_string = arguments[3];
const auto process_address = strtoull(address_string, nullptr, 16);
auto process_memory_address = reinterpret_cast<PVOID>(process_address);
if (argument_count < 4)
{
return EXIT_FAILURE;
}
const auto memory_size = arguments[4];
mem_size = strtoul(memory_size, nullptr, 10);
const auto nt_free_virtual_memory = reinterpret_cast<nt_free_virtual_memory_func>(GetProcAddress(
GetModuleHandle(L"ntdll.dll"), "NtFreeVirtualMemory"));
const auto status = nt_free_virtual_memory(process_handle, &process_memory_address, &mem_size, MEM_RELEASE);
return status;
}
int main(const int argument_count, char* arguments[])
{
if (argument_count < 4)
{
return EXIT_FAILURE;
}
const auto process_id_string = arguments[1];
const auto process_id = strtoul(process_id_string, nullptr, 10);
enable_allocating_executable_memory();
const auto process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_id);
if (process_handle == nullptr)
{
std::cout << "Cannot open process with process id " << process_id << std::endl;
exit(EXIT_FAILURE);
}
const PVOID process_memory = nullptr;
SIZE_T mem_size;
const auto command = arguments[2];
if (strcmp(command, "--allocate") == 0)
{
allocate_memory(arguments, process_handle, process_memory, mem_size);
}
else if (strcmp(command, "--free") == 0)
{
return free_memory(argument_count, arguments, process_handle, mem_size);
}
return EXIT_SUCCESS;
}
NtAllocateVirtualMemory does not seem to accept an argument for a module. What else can be used?
The reasoning behind this is that I don't want to have jmps going from one module to another after I allocated some memory but rather stay as locally as possible. This also makes jmp instructions shorter in terms of their sizes in memory.
I want to allocate some memory inside a specific module
You cannot do this, when a module is mapped it's memory is allocated. You can't allocate memory inside the module, the module exists inside it's allocated pages and no where else. Any allocated pages will be outside of the module.
Alternatively if you want to use memory which is already allocated but is not used, this called a code cave. It's typically an area of memory inside a module which is filled with zeros. So you can scan for a code cave by finding a certain length of redundant zeros inside the module and then you can write to that memory.
This is done frequently and is especially useful if the page has the execute bit set as you won't have to change any permissions which could be deemed risky.
This is also done frequently in injectors which use "scatter mapping" where it only uses these code caves to inject code.

With MODULEENTRY32 and MODULEINFO, what are the steps to scan for a specific INT value in a separate process?

I have enumerated a processes modules and have a MODULEINFO. From that I have a base address, size of the module, and the entrypoint. If I have a separate process with an integer int x = 4 defined in main(), can I scan for that integer's address using what I have with MODULEINFO? Wouldn't x exist on the stack, which is separate from the module exe?
I tried making a loop with the base address and SizeOfImage member, casting the base address to a byte*, and then adding 1 byte and then casting it to a int* to search for a specific value, however every value I got back was a "0". I believe my method was (grossly) incorrect.
If it is possible to scan an int value can anyone point me in the general direction to do so?
Yes--local variables (non-static ones, anyway) are allocated on the stack. To see their values, you'll need to write something on the order of a debugger, such as pausing the program while it's running (and the function containing the variable of interest is active), and walk the stack to find the value.
Since you're apparently using Windows, functions you'll probably want to look at include:
WaitForDebugEvent (or WaitForDebugEventEx)
ContinueDebugEvent
Stackwalk64
You'll probably also want to look at the dbghlp API, probably starting with these:
SymInitialize
SymFromName
SymCleanup
There's a lot more there to consider, but that's probably enough to at least get a bit of a start. I previously posted an answer that demonstrates StackWalk64, and some of the Sym* stuff.
Here's some code with the bare skeleton of a debugger that will spawn a child process, and then log the debug events it produces:
#include <windows.h>
#include <stdio.h>
#include "child_process.h"
void dispatch_child_event(DEBUG_EVENT const &event, child_process const &child) {
char *file_name;
char buffer[512];
switch ( event.dwDebugEventCode ) {
case LOAD_DLL_DEBUG_EVENT:
file_name = child.get_string(event.u.LoadDll.lpImageName);
if ( event.u.LoadDll.fUnicode)
printf("Loading %S\n", (wchar_t *)file_name);
else
printf("Loading %s\n", file_name);
break;
case EXCEPTION_DEBUG_EVENT:
switch (event.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
{
if ( event.u.Exception.dwFirstChance)
break;
EXCEPTION_RECORD const &r = event.u.Exception.ExceptionRecord;
printf("Access Violation %x at %0#p\n",
r.ExceptionCode,
r.ExceptionAddress);
break;
}
case EXCEPTION_BREAKPOINT:
printf("Breakpoint reached\n");
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
if ( !event.u.Exception.dwFirstChance)
printf("Misaligned data exception.\n");
break;
case EXCEPTION_SINGLE_STEP:
printf("Single Step...\n");
break;
case DBG_CONTROL_C:
if ( !event.u.Exception.dwFirstChance)
printf("Control+C pressed\n");
break;
break;
}
case CREATE_THREAD_DEBUG_EVENT:
printf("Client created a thread\n");
break;
case CREATE_PROCESS_DEBUG_EVENT:
printf("Create-Process\n");
break;
case EXIT_THREAD_DEBUG_EVENT:
printf("Thread exited.\n");
break;
case UNLOAD_DLL_DEBUG_EVENT:
printf("DLL being unloaded\n");
break;
case OUTPUT_DEBUG_STRING_EVENT: {
OUTPUT_DEBUG_STRING_INFO const &d = event.u.DebugString;
char *string = child.get_debug_string(d.lpDebugStringData,
d.nDebugStringLength);
if ( d.fUnicode)
printf("Debug string: %S\n", string);
else
printf("Debug string: %s\n", string);
break;
}
}
}
int main(int argc, char **argv) {
DEBUG_EVENT event;
if ( argc < 2 ) {
fprintf(stderr, "Usage: Trace [executable|PID]");
return EXIT_FAILURE;
}
child_process child(argv[1]);
do {
WaitForDebugEvent(&event, INFINITE);
dispatch_child_event(event, child);
ContinueDebugEvent( event.dwProcessId,
event.dwThreadId,
DBG_CONTINUE );
} while ( event.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT);
return 0;
}
That uses the following child_process header:
#ifndef CHILD_PROCESS_H_INC_
#define CHILD_PROCESS_H_INC_
#include <windows.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <io.h>
#include "syserror.h"
struct no_spawn {
no_spawn() { system_error("Spawning Program"); }
};
class child_process {
HANDLE process_;
HANDLE thread_;
mutable char buffer[FILENAME_MAX];
public:
child_process(char const *filename);
char *get_string(void *string_name, DWORD num = 0) const;
char *get_debug_string(void *string, DWORD num) const;
HANDLE process() { return process_; }
HANDLE thread() { return thread_; }
~child_process() { CloseHandle(process()); }
};
#endif
The implementation of that class is as follows:
#include "child_process.h"
static BOOL find_image(char const *name, char *buffer) {
// Try to find an image file named by the user.
// First search for the exact file name in the current
// directory. If that's not found, look for same base name
// with ".com", ".exe" and ".bat" appended, in that order.
// If we can't find it in the current directory, repeat
// the entire process on directories specified in the
// PATH environment variable.
//
#define elements(array) (sizeof(array)/sizeof(array[0]))
static char *extensions[] = {".com", ".exe", ".bat", ".cmd"};
int i;
char temp[FILENAME_MAX];
if (-1 != _access(name, 0)) {
strcpy(buffer, name);
return TRUE;
}
for (i=0; i<elements(extensions); i++) {
strcpy(temp, name);
strcat(temp, extensions[i]);
if ( -1 != _access(temp, 0)) {
strcpy(buffer, temp);
return TRUE;
}
}
_searchenv(name, "PATH", buffer);
if ( buffer[0] != '\0')
return TRUE;
for ( i=0; i<elements(extensions); i++) {
strcpy(temp, name);
strcat(temp, extensions[i]);
_searchenv(temp, "PATH", buffer);
if ( buffer[0] != '\0')
return TRUE;
}
return FALSE;
}
child_process::child_process(char const *filename) {
if (isdigit(filename[0])) {
DWORD id = atoi(filename);
process_ = OpenProcess(PROCESS_ALL_ACCESS, false, atoi(filename));
DebugActiveProcess(id);
}
else {
char buf[FILENAME_MAX];
PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
si.cb = sizeof(si);
if (!find_image(filename, buf))
throw no_spawn();
BOOL new_process_ = CreateProcess(buf, NULL, NULL, NULL, FALSE,
DEBUG_ONLY_THIS_PROCESS,
NULL, NULL,
&si, &pi);
if (!new_process_)
throw no_spawn();
CloseHandle(pi.hThread);
process_ = pi.hProcess;
thread_ = pi.hThread;
}
}
char *child_process::get_string(void *string_name, DWORD num) const {
// string_name is a pointer to a pointer to a string, with the pointer and the
// string itself located in another process_. We use Readprocess_Memory to read
// the first pointer, then the string itself into our process_ address space.
// We then return a pointer (in our address space) to the string we read in.
//
char *ptr;
SIZE_T bytes_read;
if ( 0 == num )
num = sizeof(buffer);
if ( string_name == NULL )
return NULL;
ReadProcessMemory(process_,
string_name,
&ptr,
sizeof(ptr),
&bytes_read);
if (NULL == ptr )
return NULL;
ReadProcessMemory(process_,
ptr,
buffer,
num,
&bytes_read);
return buffer;
}
char *child_process::get_debug_string(void *string, DWORD num) const {
static char buffer[FILENAME_MAX];
SIZE_T bytes_read;
if ( string == NULL )
return NULL;
ReadProcessMemory(process_,
string,
buffer,
num,
&bytes_read);
return buffer;
}
That's not enough to do everything you want yet, but at least it should give you a start in the general direction.
Oh, one disclaimer: I wrote most of this code quite a long time ago. There are parts I'd certainly do differently if I were to write it today.

wcslen quits silently when string returned by the ReadConsoleOutputCharacterW has some particular length

compiler : http://sourceforge.net/projects/mingwbuilds/files/
#include <iostream>
#include <string.h>
#include <windows.h>
using namespace std;
const wchar_t* readConsole(int chars_to_read) {
wchar_t* wcharFromConsole = new wchar_t[chars_to_read+1];
COORD pos = {0,0};
DWORD dwChars;
if (!ReadConsoleOutputCharacterW(
GetStdHandle(STD_OUTPUT_HANDLE),
wcharFromConsole, // Buffer where store symbols
chars_to_read, // number of chars to read
pos, // Read from row=8, column=6
&dwChars // How many symbols stored
))
{
printf("ReadConsoleOutputCharacterW failed %d\n", GetLastError());
abort();
}
wcharFromConsole [dwChars] = L'\0'; // Terminate, so string functions can be used
wstring ws = wcharFromConsole;
return ws.c_str();
}
int main() {
for (int i = 1; i<=0x3000; i++) {
printf("wcslen: %X \n",wcslen(readConsole(i)));
}
system("pause");
}
This loop ends at 0x1FF1 and pause is not called. Removing wstring seems to do away with this problem. But I need it here for functions like trimming white-space etc.. it is not much relevant here, but why invoking wstring causes that issue anyway ? There is no error message the program simply quits.
Updated code, now loop quits at 0x2BBF
#include <iostream>
#include <string.h>
#include <windows.h>
using namespace std;
const wchar_t* readConsole(int chars_to_read) {
wchar_t* wcharFromConsole = new wchar_t[chars_to_read+1];
COORD pos = {0,0};
DWORD dwChars;
if (!ReadConsoleOutputCharacterW(
GetStdHandle(STD_OUTPUT_HANDLE),
wcharFromConsole, // Buffer where store symbols
chars_to_read, // number of chars to read
pos, // Read from row=8, column=6
&dwChars // How many symbols stored
))
{
printf("ReadConsoleOutputCharacterW failed %d\n", GetLastError());
abort();
}
wcharFromConsole [dwChars] = L'\0'; // Terminate, so string functions can be used
wstring ws = wcharFromConsole;
delete [] wcharFromConsole;
const wchar_t* wc = ws.c_str();
return wc;
}
int main() {
for (int i = 1; i<=0x3000; i++) {
printf("wcslen: %X \n",wcslen(readConsole(i)));
}
system("pause");
}
Ouch.
wstring ws = wcharFromConsole;
return ws.c_str();
Basically, you are returning a dead pointer here. The string will be destroyed on the return, so the pointer arriving at the caller will be invalid.
EDIT: you're also leaking memory, since the "new" is never deleted. But that doesn't generally cause visible problems, just increasing memory use of the program.