GlobalSize function used on Clipboard Data cause error - c++

The first thing I want to say is my English is pretty bad so if my description become a chunk of nonsense text please comment so I can try to clarify my question.
The situation
I'm trying to access clipboard and store all of it's data from all formats possible. I listen to WM_CLIPBOARDUPDATE message then loop through all the format available, get the data for each of the format, get the size then allocate a new memory for them. My googling tell me to use the GlobalSize() function to do that. There the problem arise.
The environment
I am developing a Win32 desktop application using C++ on Visual C++ 2017 version 4.7.02556. I am using Windows 10 64 bits if that matter.
Reproducing the error
Here is my function used to process Windows messages, I remove other message like WM_CREATE or WM_DESTROY because they don't relate to the problem. The consoleOutput() function is used for debugging and they works just fine.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
switch (message){
case WM_CLIPBOARDUPDATE: {
try {
if (OpenClipboard(hWnd)){
UINT uFormat = EnumClipboardFormats(0); // Get the first clipboard format available
HANDLE hContent;
while (uFormat) { //Iterate through all formats
hContent = GetClipboardData(uFormat); // Get the clipboard data of that format
if (hContent) {
SIZE_T size = GlobalSize(hContent); // Get the size of the data I just got
//ERROR
}
uFormat = EnumClipboardFormats(uFormat); // Get the next format
}
}
CloseClipboard();
}
catch (int error) {
CloseClipboard(); // Attempt to close clipboard if thing went wrong
consoleOutput(GetLastError());
throw;
}
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
The code works fine with everything I tried to copy from text to some random files/directories. But my program gave me an error when I tried to copy a image, for example:
Open an image using MS Paint, select any portion of the image and copy it and the error appears.
Open an image using Picasa, right click and select copy and the error appears.
Press PrntScr button and the error appears.
The error is throwed at SIZE_T size = GlobalSize(hContent); line, and it is either:
Critical error detected c0000374 YClipboard.exe has triggered a breakpoint.
or
Exception thrown at 0x77E17ECC (ntdll.dll) in YClipboard.exe: 0xC0000005: Access violation reading location 0xDD46116F.
The error is not persistent, most of the time it appeared right in the first copy, sometime I can copy the image, but do it multiple times with that same image cause the error. Above all, only attempt to copy "image" data cause the problem.
What I have tried so far
I am a novice about developing desktop app, and I my searching don't find the problem anywhere else. When I peek at the clipboard data using a third-party app, I found out the error only appear when my program met the CF_BITMAP or CF_METAFILEPICT format, and (not so) coincidentally both of those formats have a memory of size 0. Still I am unable to fix my problem.
What I need
Someone please enlighten me about this problem: what is the problem, the cause of it, how to fix it or just a suggestion about another method that help me read the size of clipboard data to replace GlobalSize() function.
Thanks in advance.

Not all clipboard formats present an HGLOBAL that you can use with functions like GlobalSize().
For example, CF_BITMAP presents a handle to a bitmap; an HBITMAP that you can use with functions like GetObject().
You'll need to handle those formats specially. See the Standard Clipboard Formats list on MSDN for more information.

Related

How to replace (hook) a Windows function with a custom one using MS Detours?

I'm a student and just learned about hooking with MS Detours.
DESCRIPTION:
I wanted to replace some Windows functions for writing and changing text inside windows, titles etc. like a TextOutW() function
The TextOut() function writes a character string at the specified location, using the currently selected font, background color, and text color.
THE GOAL:
My goal is to hook new functions (like NewTextOutW()) which are going to do the same thing, but they will translate the text in another language. The new functions have the same parameters like the original ones.
WHY MS DETOURS?
I have to use MS Detours because the traditional hooking with asm and overwriting the hot-patch header of an original function works just for the X86 version of the app but not for X64, so because the MS Detours is compatible with 32bit and 64bit apps, I want to use MS Detorus.
I want to do the hooking with function addresses, because I have the source code and I have addresses of the original and the new function saved in a BYTE* type of variable.
CODE INFO:
This is my code which is going to attach a new function to the original one using the 2 adresses (BYTE* m_pOrigFunc and BYTE* m_pDetourFunc).
m_pOrigFunc is an adress of the original function and the m_pDetourFunc is the address of the function which is going to be attached to the original one. To detach the two functions I use the same code but except using the DetourAttach((PVOID*)&m_pOrigFunc, m_pDetourFunc) i use the DetourDetach((PVOID*)&m_pOrigFunc, m_pDetourFunc) statement.
CODE:
LONG err_cd = DetourTransactionBegin();
if (err_cd == NO_ERROR)
{
//err_cd = DetourUpdateThread(GetCurrentThread());
if (err_cd == NO_ERROR)
{
err_cd = DetourAttach((PVOID*)&m_pOrigFunc, m_pDetourFunc);
if (err_cd == NO_ERROR)
{
err_cd = DetourTransactionCommit();
if (err_cd == NO_ERROR)
::Trace(2, _T("MSDetours::DetourTransactionCommit: Detour erfolgreich."));
else
AbortAndTraceMSDetours("DetourTransactionCommit", err_cd);}
else
AbortAndTraceMSDetours("DetourAttach", err_cd);}
else
AbortAndTraceMSDetours("DetourUpdateThread", err_cd);}
else
AbortAndTraceMSDetours("DetourTransactionBegin", err_cd);
THE PROBLEM:
After implementig this code I got an error in some other windows function (I thing for the creating a frame but I'm not sure) which you can see
here. For the people who don't speak german, here is a text translation:
Unhandled exception at 0x6D0A00C8 in Konfig32.exe: 0xC000041D:
unhandled exception was encountered during a user callback.
The error accures with or without commenting the line with err_cd = DetourUpdateThread(GetCurrentThread()); statement.
Can someone help me to find the soolution for this problem?

SendMessage to 64bit application is not working

I use the following function to send message to application. It seems to work find for a 32bit application but doesn't work for a 64bit application (the 64bit application does not seem to get any message). What is wrong and how can I fix it? Thank you.
void MyTest::SendCmd(HWND hwnd, QString cmd)
{
COPYDATASTRUCT data;
data.dwData = FIXHEADER;
data.cbData = cmd.size()+1;
data.lpData = cmd.toLocal8Bit().data();
LPARAM lpdwResult;
LRESULT err = SendMessageTimeout(hwnd, WM_COPYDATA, 0, (LPARAM)&data, SMTO_ABORTIFHUNG, 2000, &lpdwResult);
}
//FIXHEADER is a fixed hex value that the application checks against to make sure the message is sent intentional for it.
You need to compile your application in 64-bit mode otherwise this cannot work and 64-bit handles are truncated making them invalid.
Some reading for you:
https://learn.microsoft.com/en-us/windows/desktop/winauto/32-bit-and-64-bit-interoperability

Error reading character of string - Access violation error C++

I working with a Kinect v2 related project in C++ while I cannot use Depth Frame (BYTE*) outside the function.
It works for first some minutes I think by luck so.
Then I got errors like:
Error reading characters of string
and Access violation error and no symbols loaded for kinect20.dll at some point of time.
Here is the method I am calling the values.
BYTE* bodyIndex = new BYTE[512*424]; // initialization
HRESULT frameGet(){
//Initialization method if success
hr = pDepthFrame->AccessUnderlyingBuffer(&m_nDepthBufferSize, &bodyIndex); //Kinect dll method
prints(depth[300]); // Prints the value every time
return hr;
}
HRESULT getDepthFrame(){
if frameGet is success
prints(bodyIndex[300]); // throws error reading character of string
return hr;
}
Can anyone please explain how I can access the bodyIndex data everytime.
I didnt get any response when posted the full code so need the logic how c++ works.
If assumption is right the depth data got cleaned up after sometimes by kinectdll so it reflects.
I tried with memcpy the error still there.
Thanks in advance.
According to https://msdn.microsoft.com/en-us/library/microsoft.kinect.kinect.idepthframe.accessunderlyingbuffer.aspx
you don't need to allocate the memory.
Gets a pointer to the depth frame data.
public:
HRESULT AccessUnderlyingBuffer(
UINT *capacity,
UINT16 **buffer
)
buffer Type: UINT16 [out] When this method returns, contains the
pointer to the depth frame data.
If I understand the spec correctly you have always call AccessUnderlyingBuffer() before access to it.

Getting all text from Notepad++ document in c++ for Notepad++ plugin

I am writing a plugin for notepad++ with visual studio 2013 (C++).
How can I get all text from notepad++ documantation?
There is a SCI_GETTEXT function for this. I use sendMessage function.(e.g ::SendMessage(curScintilla, SCI_GETTEXT, end, null))
But this function returns long value. Can I convert this long value to char or how can I do this in other way?
SCI_GETTEXT doesn't work without sendMessage funtion.
If I understood correctly their documentation You will have to send the WM_GETTEXT message to the handle of the editor window, where wParam will be the length of text you can accomodate and lParam will be the address of the preallocated data. After SendMessage returns you are suppsoed to have the data populated.
(I am not familiar with the SCI_...stuff , this is the "oldschool" way of solving this problem :) )

Holding scroll-bar gets command prompt to pause in Windows

I have a program where I record data through an ADC system from National Instruments (NI).
The device buffers information for some time, and then the program collects the buffer data at some point. If the program collects data larger than the buffer, then the buffer would have to free without my program receiving the data, which will cause the NI library to throw an exception saying that requested data isn't available anymore, since it was lost.
Since my program is a command-prompt program, if the user clicks and holds the scrollbar, the program pauses, which could get this problem to happen.
How can I get over this problem without increasing the buffer size? Can I disable this holding thing in Windows?
Thanks.
Only the thread that is attempting to output to the console is blocked. Make this a separate thread, and your problem goes away.
Of course, you'll need to buffer up your output, and do something sensible if the buffer overflows.
For reference, here's the simple code I used to test this, you will note that the counter continues to increase even when the scroll bar is held down:
#include <Windows.h>
#include <stdio.h>
volatile int n = 0;
DWORD WINAPI my_thread(LPVOID parameter)
{
for (;;)
{
n = n + 1;
Sleep(800);
}
}
int main(int argc, char ** argv)
{
if (!CreateThread(NULL, 0, my_thread, NULL, 0, NULL))
{
printf("Error %u from CreateThread\n", GetLastError());
return 0;
}
for (;;)
{
printf("Hello! We're at %u\n", n);
Sleep(1000);
}
return 0;
}
Whilst there may be ways to bypass each individual problem you can possibly conceive with the output [including for example running it over a network on a sometimes slow output link, or some such], I think the correct thing to do is to disconnect your output from your collecting of data. It shouldn't be hard to do this by adding a separate thread that collects the data, and having the main thread display to the command prompt window. That way, not matter which variation of "output is blocked" Windows throws at you, it will work - at least until you run out of RAM, but tat that point it's YOUR program's decision to do something [e.g. throw away some data or some such].
This is generally how the problem "I need to collect something, and I also need to allow users to view the data, but I don't want the two to interfere with each other" is solved.
First use the GetConsoleWindow winapi function and get the HWND of your console.
now i suggest two ways to do this,
Method I
Subclass the window by creating your own WindowProcedure. (get help from here)
Now that you have subclassed it, you can intercept the WM_VSCROLL and WM_HSCROLL messages and do your own remedy to your code.
Method II
Change the size of the window using some function like SetWindowPos so that the scroll bars are not needed.
or Change the size of the console screen buffer so that the scroll bars are not needed.
Method I has lot of control over the application, but its a little bit complex than the method II which is very simple.
If you want to forbid the user from resizing the console window, just remove the WS_THICKFRAME from the WindowStyle of the console window.
I was in a similar situation and found that this kind of blocking behaviour could be caused by the quick edit "feature" of the command prompt. This question explains about it and the answer shows how to disable it. Hope that helps, even after some years :)