How to handle xcb client messages properly - c

The following code creates a window with a opengl rendering context.
Everything works fine, but somehow the window close event doesn't correlate to the wm_delete_window atom.
static int
hnd_connect_to_xcb
(
hnd_linux_window_t *_window
)
{
_window->renderer.display = XOpenDisplay((char *)NULL);
if (!hnd_assert(_window->renderer.display != NULL, "Could not open display"))
return HND_NK;
_window->renderer.default_screen = DefaultScreen(_window->renderer.display);
_window->connection = XGetXCBConnection(_window->renderer.display);
if (!hnd_assert(_window->connection != NULL, "Could not connect to X display"))
return HND_NK;
XSetEventQueueOwner(_window->renderer.display, XCBOwnsEventQueue);
/* Get screen data */
xcb_screen_iterator_t screen_iterator = xcb_setup_roots_iterator(xcb_get_setup(_window->connection));
for (int i = _window->renderer.default_screen; i > 0; --i)
xcb_screen_next(&screen_iterator);
_window->screen_data = screen_iterator.data;
if (!hnd_set_fb_configs(&_window->renderer))
return HND_NK;
return HND_OK;
}
static void
hnd_set_window_properties
(
hnd_linux_window_t *_window
)
{
/* Set title */
xcb_intern_atom_cookie_t utf8_string_cookie =
hnd_create_intern_atom_cookie(_window->connection, HND_NK, "UTF8_STRING");
_window->utf8_string = hnd_create_intern_atom_reply(_window->connection, utf8_string_cookie);
xcb_intern_atom_cookie_t wm_name_cookie =
hnd_create_intern_atom_cookie(_window->connection, HND_NK, "WM_NAME");
_window->wm_name = hnd_create_intern_atom_reply(_window->connection, wm_name_cookie);
xcb_change_property(_window->connection,
XCB_PROP_MODE_REPLACE,
_window->id,
_window->wm_name->atom,
_window->utf8_string->atom,
8,
strlen(_window->title),
_window->title);
/* Add listener for close event */
xcb_intern_atom_cookie_t wm_protocols_cookie =
hnd_create_intern_atom_cookie(_window->connection, HND_OK, "WM_PROTOCOLS");
_window->wm_protocols = hnd_create_intern_atom_reply(_window->connection, wm_protocols_cookie);
xcb_intern_atom_cookie_t wm_delete_cookie =
hnd_create_intern_atom_cookie(_window->connection, HND_NK, "WM_DELETE_WINDOW");
_window->wm_delete_window = hnd_create_intern_atom_reply(_window->connection, wm_delete_cookie);
xcb_change_property(_window->connection,
XCB_PROP_MODE_REPLACE,
_window->id,
_window->wm_protocols->atom,
XCB_ATOM_ATOM,
32,
1,
&_window->wm_delete_window->atom);
}
hnd_linux_window_t *
hnd_create_window
(
const char *_title,
unsigned int _left,
unsigned int _top,
unsigned int _width,
unsigned int _height,
unsigned int _decoration
)
{
hnd_linux_window_t *new_window = malloc(sizeof(hnd_linux_window_t));
if (!hnd_assert(new_window != NULL, NULL))
return NULL;
if (!hnd_connect_to_xcb(new_window))
return NULL;
new_window->title = (char *)_title;
new_window->left = _left;
new_window->top = _top;
new_window->width = _width;
new_window->height = _height;
new_window->running = HND_OK;
if (!hnd_init_renderer(&new_window->renderer))
{
hnd_destroy_window(new_window);
return NULL;
}
new_window->colormap_id = xcb_generate_id(new_window->connection);
xcb_create_colormap(new_window->connection,
XCB_COLORMAP_ALLOC_NONE,
new_window->colormap_id,
new_window->screen_data->root,
new_window->renderer.visual_id);
new_window->value_mask = XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
new_window->event_mask = XCB_EVENT_MASK_EXPOSURE |
XCB_EVENT_MASK_BUTTON_PRESS |
XCB_EVENT_MASK_BUTTON_RELEASE |
XCB_EVENT_MASK_POINTER_MOTION |
XCB_EVENT_MASK_BUTTON_MOTION |
XCB_EVENT_MASK_ENTER_WINDOW |
XCB_EVENT_MASK_LEAVE_WINDOW |
XCB_EVENT_MASK_KEY_PRESS |
XCB_EVENT_MASK_KEY_RELEASE;
new_window->value_list[0] = new_window->event_mask;
new_window->value_list[1] = new_window->colormap_id;
/* Create window */
new_window->id = xcb_generate_id(new_window->connection);
xcb_create_window(new_window->connection,
XCB_COPY_FROM_PARENT,
new_window->id,
new_window->screen_data->root,
new_window->left,
new_window->top,
new_window->width,
new_window->height,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
new_window->renderer.visual_id,
new_window->value_mask,
new_window->value_list);
hnd_set_window_properties(new_window);
hnd_set_window_decoration(new_window, _decoration);
xcb_map_window(new_window->connection, new_window->id);
xcb_flush(new_window->connection);
/* Finish opengl binding */
new_window->renderer.gl_window = glXCreateWindow(new_window->renderer.display,
new_window->renderer.current_fb_config,
new_window->id,
0);
if (!hnd_assert(new_window->renderer.gl_window, "Could not create OpenGL window"))
{
hnd_destroy_window(new_window);
return NULL;
}
if (!hnd_assert(glXMakeContextCurrent(new_window->renderer.display,
new_window->renderer.gl_window,
new_window->renderer.gl_window,
new_window->renderer.gl_context),
"Could not set OpenGL current rendering context"))
{
hnd_destroy_window(new_window);
return NULL;
}
hnd_print_debug(HND_LOG, HND_CREATED("OpenGL context"), HND_SUCCESS);
hnd_print_debug(HND_LOG, HND_CREATED("window"), HND_SUCCESS);
return new_window;
}
void
hnd_destroy_window
(
hnd_linux_window_t *_window
)
{
if (!hnd_assert(_window != NULL, HND_SYNTAX))
return;
hnd_end_renderer(&_window->renderer);
xcb_free_colormap(_window->connection, _window->colormap_id);
hnd_print_debug(HND_LOG, HND_ENDED("window"), HND_SUCCESS);
}
void
hnd_poll_events
(
hnd_linux_window_t *_window,
hnd_event_t *_event
)
{
if (!hnd_assert(_window != NULL, HND_SYNTAX))
return;
if (!hnd_assert(_event != NULL, HND_SYNTAX))
return;
_event->xcb_event = xcb_poll_for_event(_window->connection);
if (!_event->xcb_event)
return;
switch (_event->xcb_event->response_type & 0x7f)
{
case XCB_EXPOSE:
xcb_flush(_window->connection);
break;
case XCB_KEY_PRESS:
hnd_queue_key_event(_event->pressed_keys, _event->xcb_event);
break;
case XCB_KEY_RELEASE:
hnd_queue_key_event(_event->released_keys, _event->xcb_event);
break;
case XCB_CLIENT_MESSAGE:
{
xcb_client_message_event_t *temp_client_message_event = (xcb_client_message_event_t *)_event;
if (temp_client_message_event->data.data32[0] == _window->wm_delete_window->atom)
_window->running = HND_NK;
} break;
default:
break;
}
}
Most of the renderer functions won't help much, besides these two helpers that create the atoms:
xcb_intern_atom_cookie_t
hnd_create_intern_atom_cookie
(
xcb_connection_t *_connection,
unsigned int _exists,
const char *_string
)
{
return xcb_intern_atom(_connection, _exists, strlen(_string), _string);
}
xcb_intern_atom_reply_t *
hnd_create_intern_atom_reply
(
xcb_connection_t *_connection,
xcb_intern_atom_cookie_t _cookie
)
{
xcb_intern_atom_reply_t *new_atom_reply = xcb_intern_atom_reply(_connection, _cookie, NULL);
if (!hnd_assert(new_atom_reply != NULL, "Could not create atom"))
return NULL;
return new_atom_reply;
}
And yes, I'm including external files. Everything compiles correctly.

The problem is basically a typo:
_event->xcb_event = xcb_poll_for_event(_window->connection);
[...]
switch (_event->xcb_event->response_type & 0x7f)
{
[...]
case XCB_CLIENT_MESSAGE:
{
xcb_client_message_event_t *temp_client_message_event = (xcb_client_message_event_t *)_event;
You are saving the event in _event->xcb_event. But you are casting _event to xcb_client_message_event_t*. You should be casting _event->xcb_event.
So, that last line should be:
xcb_client_message_event_t *temp_client_message_event = (xcb_client_message_event_t *)_event->xcb_event;

Related

Why is config_read_file() returning config_false?

I have been using libconfig for config files in a project. When I remove the double quotes from sources by source_to_use, config_read_file() returns config_true and also has a syntax error. The syntax error will cause my getter for the source_to_use option to go to the default case. Also because of this my getter for the source array, will also go to the else case. Could this just be me making a simple syntax error with the libconfig format?
This is the config file I am using:
#config for walld
#colors
colors = TRUE;
source_to_use: "sources";
default:
[
"/home/seth/Pictures/kimi.png"
];
sources:
[
"/home/seth/.walld/persona",
"/home/seth/.walld/image-urls"
];
This is the function I have reading it:
settings* read_config(const char* config_file, const char* home_dir) {
settings* options = malloc(sizeof(settings));
config_t config;
config_setting_t* setting;
const char* source;
int colors;
config_init(&config);
if (config_read_file(&config, config_file) == CONFIG_TRUE) {
config_destroy(&config);
return NULL;
}
if (config_lookup_bool(&config, "colors", &colors)) {
options->colors = colors;
}
else {
options->colors = 0;
}
if (config_lookup_string(&config, "source_to_use", &source)) {
//NOP
}
else {
source = "default";
}
setting = config_lookup(&config, source);
if (setting != NULL) {
int count = config_setting_length(setting);
linked_node* entry_point = add_node_to_list(NULL, NULL);
linked_node* current = entry_point;
options->sources = entry_point;
for (int i = 0; i < count; i++) {
char* item = config_setting_get_string_elem(setting, i);
current = add_node_to_list(current, item);
}
}
else {
options->sources = malloc(sizeof(linked_node));
int char_count = snprintf(NULL, 0, "%s%s", home_dir, "/.walld/images");
if (char_count <= 0) {
//tough luck
abort();
}
char* default_folder = malloc(char_count + 1U);
if (default_folder == NULL) {
//tough luck
abort();
}
snprintf(default_folder, char_count + 1U, "%s%s", home_dir, "/.walld/images");
options->sources->image = default_folder;
}
config_destroy(&config);
return options;
}
In your read_config function, your first if is:
if (config_read_file(&config, config_file) == CONFIG_TRUE) {
config_destroy(&config);
return NULL;
}
The sense of the if is reversed, so you'll return a NULL if the read of the file is valid.
So, you want to reverse the sense of this if:
if (config_read_file(&config, config_file) != CONFIG_TRUE) {
config_destroy(&config);
return NULL;
}
Or you could [probably] use:
if (config_read_file(&config, config_file) == CONFIG_FALSE) {

avcodec_encode_video2 the memory usage is very high

code:
```
#include "pch.h"
#include
extern "C"
{
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif
#include <libavcodec/avcodec.h>
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/avutil.h"
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
#include <libavutil/rational.h>
//#include "libavutil/avassert.h"
//#include "libavutil/attributes.h"
//#include "libavutil/avassert.h"
//#include "libavutil/frame.h"
//#include "libavutil/imgutils.h"
//#include "internal1.h"
//#include "libavutil/samplefmt.h"
}
#include <vld.h>
//#include "avcodec.h"
//#include "frame_thread_encoder.h"
//#include "internal.h"
// Globals
AVCodec* m_pCodec = NULL;
AVStream *m_pStream = NULL;
AVOutputFormat* m_pFormat = NULL;
AVFormatContext* m_pFormatContext = NULL;
AVCodecContext* m_pCodecContext = NULL;
AVFrame* m_pFrame = NULL;
int m_frameIndex;
// Output format
AVPixelFormat m_pixType = AV_PIX_FMT_NV12;
// Use for mpeg4
//AVPixelFormat m_pixType = AV_PIX_FMT_YUV420P;
// Output frame rate
int m_frameRate = 30;
// Output image dimensions
int m_imageWidth = 256;
int m_imageHeight = 1537;
// Number of frames to export
int m_frameCount = 20000;
// Output file name
const char* m_fileName = "test.h264";
// Output file type
const char* m_fileType = "H264";
// Codec name used to encode
const char* m_encoderName = "h264_qsv";
// use for mpeg4
//const char* m_encoderName = "mpeg4";
// Target bit rate
int m_targetBitRate = 400000;
void addVideoStream()
{
m_pStream = avformat_new_stream(m_pFormatContext, m_pCodec);
m_pStream->id = m_pFormatContext->nb_streams - 1;
m_pStream->time_base = m_pCodecContext->time_base;
m_pStream->codec->pix_fmt = m_pixType;
m_pStream->codec->flags = m_pCodecContext->flags;
m_pStream->codec->width = m_pCodecContext->width;
m_pStream->codec->height = m_pCodecContext->height;
m_pStream->codec->time_base = m_pCodecContext->time_base;
m_pStream->codec->bit_rate = m_pCodecContext->bit_rate;
}
AVFrame* allocatePicture(enum AVPixelFormat pix_fmt, int width, int height)
{
AVFrame *frame;
frame = av_frame_alloc();
if (!frame)
{
return NULL;
}
frame->format = pix_fmt;
frame->width = width;
frame->height = height;
int checkImage = av_image_alloc(frame->data, frame->linesize, width, height, pix_fmt, 32);
if (checkImage < 0)
{
return NULL;
}
return frame;
}
bool initialize()
{
AVRational frameRate;
frameRate.den = m_frameRate;
frameRate.num = 1;
av_register_all();
m_pCodec = avcodec_find_encoder_by_name(m_encoderName);
if (!m_pCodec)
{
return false;
}
m_pCodecContext = avcodec_alloc_context3(m_pCodec);
m_pCodecContext->width = m_imageWidth;
m_pCodecContext->height = m_imageHeight;
m_pCodecContext->time_base = frameRate;
m_pCodecContext->gop_size = 0;
m_pCodecContext->pix_fmt = m_pixType;
m_pCodecContext->codec_id = m_pCodec->id;
m_pCodecContext->bit_rate = m_targetBitRate;
av_opt_set(m_pCodecContext->priv_data, "+CBR", "", 0);
return true;
}
bool startExport()
{
m_frameIndex = 0;
char fakeFileName[512];
int checkAllocContext = avformat_alloc_output_context2(&m_pFormatContext, NULL, m_fileType, fakeFileName);
if (checkAllocContext < 0)
{
return false;
}
if (!m_pFormatContext)
{
return false;
}
m_pFormat = m_pFormatContext->oformat;
if (m_pFormat->video_codec != AV_CODEC_ID_NONE)
{
addVideoStream();
int checkOpen = avcodec_open2(m_pCodecContext, m_pCodec, NULL);
if (checkOpen < 0)
{
return false;
}
m_pFrame = allocatePicture(m_pCodecContext->pix_fmt, m_pCodecContext->width, m_pCodecContext->height);
if (!m_pFrame)
{
return false;
}
m_pFrame->pts = 0;
}
int checkOpen = avio_open(&m_pFormatContext->pb, m_fileName, AVIO_FLAG_WRITE);
if (checkOpen < 0)
{
return false;
}
av_dict_set(&(m_pFormatContext->metadata), "title", "QS Test", 0);
int checkHeader = avformat_write_header(m_pFormatContext, NULL);
if (checkHeader < 0)
{
return false;
}
return true;
}
int processFrame(AVPacket& avPacket)
{
avPacket.stream_index = 0;
avPacket.pts = av_rescale_q(m_pFrame->pts, m_pStream->codec->time_base, m_pStream->time_base);
avPacket.dts = av_rescale_q(m_pFrame->pts, m_pStream->codec->time_base, m_pStream->time_base);
m_pFrame->pts++;
int retVal = av_interleaved_write_frame(m_pFormatContext, &avPacket);
return retVal;
}
bool exportFrame()
{
int success = 1;
int result = 0;
AVPacket avPacket;
av_init_packet(&avPacket);
avPacket.data = NULL;
avPacket.size = 0;
AVPacket* avPacket1 = new AVPacket();
av_init_packet(avPacket1);
avPacket1->data = NULL;
avPacket1->size = 0;
fflush(stdout);
std::cout << "Before avcodec_encode_video2 for frame: " << m_frameIndex << std::endl;
success = avcodec_encode_video2(m_pCodecContext, &avPacket, m_pFrame, &result);
std::cout << "After avcodec_encode_video2 for frame: " << m_frameIndex << std::endl;
if (result)
{
success = processFrame(avPacket);
}
av_packet_unref(&avPacket);
av_free_packet(&avPacket);
//av_frame_free(&m_pFrame);
m_frameIndex++;
return (success == 0);
}
void endExport()
{
int result = 0;
int success = 0;
if (m_pFrame)
{
while (success == 0)
{
AVPacket avPacket;
av_init_packet(&avPacket);
avPacket.data = NULL;
avPacket.size = 0;
fflush(stdout);
success = avcodec_encode_video2(m_pCodecContext, &avPacket, NULL, &result);
if (result)
{
success = processFrame(avPacket);
}
av_packet_unref(&avPacket);
if (!result)
{
break;
}
}
}
if (m_pFormatContext)
{
av_write_trailer(m_pFormatContext);
if (m_pFrame)
{
av_frame_free(&m_pFrame);
}
avio_closep(&m_pFormatContext->pb);
avformat_free_context(m_pFormatContext);
m_pFormatContext = NULL;
}
}
void cleanup()
{
if (m_pFrame || m_pCodecContext)
{
if (m_pFrame)
{
av_frame_free(&m_pFrame);
}
if (m_pCodecContext)
{
avcodec_close(m_pCodecContext);
av_free(m_pCodecContext);
}
}
}
int main()
{
bool success = true;
if (initialize())
{
if (startExport())
{
for (int loop = 0; loop < m_frameCount; loop++)
{
if (!exportFrame())
{
std::cout << "Failed to export frame\n";
success = false;
break;
}
}
endExport();
}
else
{
std::cout << "Failed to start export\n";
success = false;
}
cleanup();
}
else
{
std::cout << "Failed to initialize export\n";
success = false;
}
if (success)
{
std::cout << "Successfully exported file\n";
}
return 1;
}
```
When I set the m_imageHeight to 1536, the memory usage is very high. But when set to 1535 or 1537 or other values, the memory usage is normal, can you tell me why?
I have navigated to avcodec_encode_video2
enter link description here
I am using the code from the link
I have updated to the latest IntelĀ® Graphics Driver

Programmatically change VersionInfo of a foreign DLL

I am trying to programmatically change the VersionInfo attributes of a DLL file. I used this article as reference.
#include <iostream>
#include <stdio.h>
#include <windows.h>
int main(int argc, char** argv) {
LPCTSTR lpszFile = "E:\\_test\\rand_test\\test.dll";
DWORD dwHandle,
dwSize;
struct {
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
// determine the size of the resource information
dwSize = GetFileVersionInfoSize(lpszFile, &dwHandle);
if (0 < dwSize)
{
unsigned char* lpBuffer = (unsigned char*) malloc(dwSize);
// Get whole VersionInfo resource/structure
GetFileVersionInfo(lpszFile, 0, dwSize, lpBuffer);
char strSubBlock[37]; // fits "\\StringFileInfo\\xxxxxxxx\\CompanyName\0"
LPTSTR pValueBuffer;
HANDLE hResource = BeginUpdateResource(lpszFile, FALSE);
if (NULL != hResource)
{
UINT uTemp;
// get the language information
if (!VerQueryValue(lpBuffer, "\\VarFileInfo\\Translation", (LPVOID *) &lpTranslate, &uTemp) != FALSE)
{
printf("Error 1\n");
return 1;
}
sprintf(strSubBlock, "\\StringFileInfo\\%04x%04x\\CompanyName", lpTranslate->wLanguage, lpTranslate->wCodePage);
if (!VerQueryValue(lpBuffer, (LPTSTR) ((LPCTSTR) strSubBlock), (LPVOID *) &pValueBuffer, &uTemp)) {
printf("Error 2\n");
return 1;
}
// PROBLEM!!!
// (pValueBuffer-lpBuffer) is 0x438 (longer than the Versioninfo resource!) but should be 0xB8
// so, pValueBuffer does not point to the actual company name.
ZeroMemory(pValueBuffer, strlen(pValueBuffer) * sizeof(TCHAR));
strcpy(pValueBuffer, "My Company, Inc."); // String may only become smaller or equal, never bigger than strlen(pValueBuffer)
if (UpdateResource(hResource,
RT_VERSION,
MAKEINTRESOURCE(VS_VERSION_INFO),
lpTranslate->wLanguage, // or 0
lpBuffer,
dwSize) != FALSE)
{
EndUpdateResource(hResource, FALSE);
}
}
free(lpBuffer);
}
return 0;
}
I think I have understood everything the code does. The plan is to read the Versioninfo block, then find the position where e.g. the CompanyName lies using VerQueryValue, then change the data, and then write it back using UpdateResource.
But there is a problem: VerQueryValue should output the position where the CompanyName string lies. But instead, it gives a pointer location, which is a few hundred bytes away, so it points somewhere outside the VersionInfo structure.
What am I doing wrong and how can I make it work?
(Also, does anybody know if there is a more elegant way to do this task, maybe even remove the limitation that the string has to be smaller or equal to the original?)
version resource this is serialized tree. if you want modify it - you need deserialize it to tree structure in memory, modify node, and serialize to new memory.
despite in msdn defined several Version Information Structures, really all it have common format
struct RsrcHeader
{
WORD wLength;
WORD wValueLength;
WORD wType;
WCHAR szKey[];
// aligned on 4*n
// BYTE Value[wValueLength]; // if (wType == 0)
// or
// WCHAR Value[wValueLength]; // if (wType == 1)
// every element aligned on 4*n
// RsrcHeader childs[];
};
so possible write common parse and serialize procedures
#if DBG
#define DBG_OPT(x) _CRT_UNPARENTHESIZE(x)
#else
#define DBG_OPT(x)
#endif
class RsrcNode
{
struct RsrcHeader
{
WORD wLength;
WORD wValueLength;
WORD wType;
WCHAR szKey[];
};
C_ASSERT(sizeof(RsrcHeader) == 6);
RsrcNode* _first, *_next;
PCWSTR _name;
const void* _pvValue;
ULONG _cbValue;
WORD _wValueLength;
WORD _wType;
DBG_OPT((PCSTR _prefix)); // only for debug output
public:
bool ParseResourse(PVOID buf, ULONG size, ULONG* pLength, PCSTR prefix);
RsrcNode(DBG_OPT((PCSTR prefix = "")))
: _next(0), _first(0) DBG_OPT((, _prefix(prefix)))
{
}
~RsrcNode();
bool IsStringValue() const
{
return _wType;
}
const void* getValue(ULONG& cb)
{
cb = _cbValue;
return _pvValue;
}
void setValue(const void* pv, ULONG cb)
{
_pvValue = pv, _cbValue = cb;
_wValueLength = (WORD)(_wType ? cb / sizeof(WCHAR) : cb);
}
RsrcNode* find(const PCWSTR strings[], ULONG n);
ULONG GetSize() const;
PVOID Store(PVOID buf, ULONG* pcb) const;
};
bool RsrcNode::ParseResourse(PVOID buf, ULONG size, ULONG* pLength, PCSTR prefix)
{
union {
PVOID pv;
RsrcHeader* ph;
ULONG_PTR up;
PCWSTR sz;
};
pv = buf;
if (size < sizeof(RsrcHeader) || (up & 3))
{
return false;
}
WORD wType = ph->wType;
ULONG wValueLength = ph->wValueLength, wLength = ph->wLength;
ULONG cbValue = 0;
switch (wType)
{
case 1:
cbValue = wValueLength * sizeof(WCHAR);
break;
case 0:
cbValue = wValueLength;
break;
default:
return false;
}
*pLength = wLength;
if (wLength > size || wLength < sizeof(RsrcHeader) || cbValue >= (wLength -= sizeof(RsrcHeader)))
{
return false;
}
wLength -= cbValue;
sz = ph->szKey, _name = sz;
do
{
if (wLength < sizeof(WCHAR))
{
return false;
}
wLength -= sizeof(WCHAR);
} while (*sz++);
DbgPrint("%s%S {\n", prefix, _name);
if (up & 3)
{
if (wLength < 2)
{
return false;
}
up += 2, wLength -= 2;
}
_wType = wType, _wValueLength = (WORD)wValueLength, _cbValue = cbValue, _pvValue = pv;
if (wValueLength && wType)
{
if (sz[wValueLength - 1])
{
return false;
}
DbgPrint("%s\t%S\n", prefix, sz);
}
if (wLength)
{
if (!*--prefix) return false;
up += wValueLength;
do
{
if (up & 3)
{
if (wLength < 2)
{
return false;
}
up += 2;
if (!(wLength -= 2))
{
break;
}
}
if (RsrcNode* node = new RsrcNode(DBG_OPT((prefix))))
{
node->_next = _first, _first = node;
if (node->ParseResourse(ph, wLength, &size, prefix))
{
continue;
}
}
return false;
} while (up += size, wLength -= size);
prefix++;
}
DbgPrint("%s}\n", prefix);
return true;
}
RsrcNode::~RsrcNode()
{
if (RsrcNode* next = _first)
{
do
{
RsrcNode* cur = next;
next = next->_next;
delete cur;
} while (next);
}
DBG_OPT((DbgPrint("%s%S\n", _prefix, _name)));
}
RsrcNode* RsrcNode::find(const PCWSTR strings[], ULONG n)
{
PCWSTR str = *strings++;
if (!str || !wcscmp(str, _name))
{
if (!--n)
{
return this;
}
if (RsrcNode* next = _first)
{
do
{
if (RsrcNode* p = next->find(strings, n))
{
return p;
}
} while (next = next->_next);
}
}
return 0;
}
ULONG RsrcNode::GetSize() const
{
ULONG size = sizeof(RsrcHeader) + (1 + (ULONG)wcslen(_name)) * sizeof(WCHAR);
if (_cbValue)
{
size = ((size + 3) & ~3) + _cbValue;
}
if (RsrcNode* next = _first)
{
do
{
size = ((size + 3) & ~3) + next->GetSize();
} while (next = next->_next);
}
return size;
}
PVOID RsrcNode::Store(PVOID buf, ULONG* pcb) const
{
union {
RsrcHeader* ph;
ULONG_PTR up;
PVOID pv;
};
pv = buf;
ph->wType = _wType;
ph->wValueLength = _wValueLength;
ULONG size = (1 + (ULONG)wcslen(_name)) * sizeof(WCHAR), cb;
memcpy(ph->szKey, _name, size);
up += (size += sizeof(RsrcHeader));
if (_cbValue)
{
up = (up + 3) & ~3;
memcpy(pv, _pvValue, _cbValue);
up += _cbValue;
size = ((size + 3) & ~3) + _cbValue;
}
if (RsrcNode* next = _first)
{
do
{
up = (up + 3) & ~3;
pv = next->Store(pv, &cb);
size = ((size + 3) & ~3) + cb;
} while (next = next->_next);
}
reinterpret_cast<RsrcHeader*>(buf)->wLength = (WORD)size;
*pcb = size;
return pv;
}
with this helper structure we can update version in next way:
#include "VerHlp.h"
BOOL UpdateVersion(PVOID pvVersion, ULONG cbVersion, PVOID& pvNewVersion, ULONG& cbNewVersion)
{
BOOL fOk = FALSE;
char prefix[16];
memset(prefix, '\t', sizeof(prefix));
prefix[RTL_NUMBER_OF(prefix) - 1] = 0;
*prefix = 0;
if (RsrcNode* node = new RsrcNode)
{
if (node->ParseResourse(pvVersion, cbVersion, &cbVersion, prefix + RTL_NUMBER_OF(prefix) - 1))
{
static const PCWSTR str[] = {
L"VS_VERSION_INFO", L"StringFileInfo", 0, L"CompanyName"
};
if (RsrcNode *p = node->find(str, RTL_NUMBER_OF(str)))
{
if (p->IsStringValue())
{
ULONG cb;
const void* pvCompanyName = p->getValue(cb);
DbgPrint("CompanyName: %S\n", pvCompanyName);
static WCHAR CompanyName[] = L"[ New Company Name ]";
if (cb != sizeof(CompanyName) ||
memcmp(pvCompanyName, CompanyName, sizeof(CompanyName)))
{
p->setValue(CompanyName, sizeof(CompanyName));
cbVersion = node->GetSize();
if (pvVersion = LocalAlloc(0, cbVersion))
{
node->Store(pvVersion, &cbNewVersion);
pvNewVersion = pvVersion;
fOk = TRUE;
}
}
}
}
}
delete node;
}
return fOk;
}
struct EnumVerData
{
HANDLE hUpdate;
BOOL fDiscard;
};
BOOL CALLBACK EnumResLangProc(HMODULE hModule,
PCWSTR lpszType,
PCWSTR lpszName,
WORD wIDLanguage,
EnumVerData* Ctx
)
{
if (HRSRC hResInfo = FindResourceExW(hModule, lpszType, lpszName, wIDLanguage))
{
if (HGLOBAL hg = LoadResource(hModule, hResInfo))
{
if (ULONG size = SizeofResource(hModule, hResInfo))
{
if (PVOID pv = LockResource(hg))
{
if (UpdateVersion(pv, size, pv, size))
{
if (UpdateResource(Ctx->hUpdate, lpszType, lpszName, wIDLanguage, pv, size))
{
Ctx->fDiscard = FALSE;
}
LocalFree(pv);
}
}
}
}
}
return TRUE;
}
ULONG UpdateVersion(PCWSTR FileName)
{
ULONG dwError = NOERROR;
EnumVerData ctx;
if (ctx.hUpdate = BeginUpdateResource(FileName, FALSE))
{
ctx.fDiscard = TRUE;
if (HMODULE hmod = LoadLibraryExW(FileName, 0, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE))
{
if (!EnumResourceLanguages(hmod, RT_VERSION,
MAKEINTRESOURCE(VS_VERSION_INFO),
(ENUMRESLANGPROCW)EnumResLangProc, (LONG_PTR)&ctx))
{
dwError = GetLastError();
}
FreeLibrary(hmod);
}
else
{
dwError = GetLastError();
}
if (!dwError && !EndUpdateResourceW(ctx.hUpdate, ctx.fDiscard))
{
dwError = GetLastError();
}
}
else
{
dwError = GetLastError();
}
return dwError;
}

ReadFile returns 0 bytes with GetLastError() as 0

I am using a generic write and read operations using the serial communication with R-232 connector to an external device.
For specific write operations, the readFile returns the data.
But for one command, it returns 0 bytes and GetLastError() returns 0.
I am using the application on a windows PDA.
Below is the code used:
long port = jport;
long baudrate = jbaudrate;
int cmd_length = env->GetStringLength(jcmd);
const jchar* cmd = env->GetStringChars(jcmd, 0);
zCommand = new char[cmd_length+1];
for (int j=0;j<cmd_length;j++)
zCommand[j] = (char)cmd[j];
zCommand[cmd_length]='\r';
env->ReleaseStringChars(jcmd,cmd);
WCHAR comPort[6];
wsprintf(comPort, L"COM%d:", port);
LPCTSTR pcCommPort = LPCTSTR( comPort );
hCom = CreateFile( pcCommPort,
GENERIC_READ | GENERIC_WRITE,
0, // exclusive-access
NULL, // default security attributes
OPEN_EXISTING,
0, // not overlapped I/O
NULL
);
if (hCom == INVALID_HANDLE_VALUE)
{
throw_executeCommand(env,"java/lang/Exception","INVALID_HANDLE_VALUE");
return env->NewStringUTF("");
}
//Clear all input output buffer
PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR);
//Configure DCB
DCB PortDCB;
// Initialize the DCBlength member.
PortDCB.DCBlength = sizeof (DCB);
// Get the default port setting information.
GetCommState (hCom, &PortDCB);
// Change the DCB structure settings.
PortDCB.BaudRate = baudrate; // Zera specified baud
PortDCB.ByteSize = 8;
PortDCB.StopBits = TWOSTOPBITS;
PortDCB.Parity = PARITY_NONE;
PortDCB.fDtrControl = DTR_CONTROL_ENABLE;
PortDCB.fRtsControl = RTS_CONTROL_ENABLE | (RTS_CONTROL_TOGGLE ^ RTS_CONTROL_HANDSHAKE );
PortDCB.fAbortOnError = FALSE;
//Set Com Timeouts
COMMTIMEOUTS commTimeouts;
if(!GetCommTimeouts(hCom, &commTimeouts))
{
throw_executeCommand(env,"java/lang/Exception","Exception GetCommTimeouts");
return env->NewStringUTF("");
}
commTimeouts.ReadIntervalTimeout = 50;
commTimeouts.ReadTotalTimeoutMultiplier = 10;
commTimeouts.ReadTotalTimeoutConstant = 50;
commTimeouts.WriteTotalTimeoutConstant = 50;
commTimeouts.WriteTotalTimeoutMultiplier = 10;
if(!SetCommTimeouts(hCom, &commTimeouts))
{
throw_executeCommand(env,"java/lang/Exception","Exception SetCommTimeouts");
return env->NewStringUTF("");
}
if (!SetCommState (hCom, &PortDCB))
{
throw_executeCommand(env,"java/lang/Exception","Exception SetCommState");
return env->NewStringUTF("");
}
unsigned long numBytesWritten;
unsigned long numBytesRead;
BOOL bWriteResult;
bWriteResult = WriteFile(hCom,zCommand, sizeof (zCommand),&numBytesWritten,NULL);
if (!bWriteResult)
{
throw_executeCommand(env,"java/lang/Exception","Exception WriteFile");
return env->NewStringUTF("");
}
//Time to read
string result="";
BOOL bReadResult; //AAV,ARC,AGR1
char sBuffer[128];
BOOL datafound;
numBytesRead = 0;
while(true)
{
bReadResult = ReadFile(hCom, &sBuffer, 128, &numBytesRead, NULL);
if (numBytesRead > 0)
{
for (int i=0;i<(int)numBytesRead;i++)
{
datafound = TRUE;
if (sBuffer[i]=='\r')
{
result += '\n';
}else
{
result += sBuffer[i];
}
}
}
else
{
break;
}
}
if (datafound)
{
if (hCom != INVALID_HANDLE_VALUE)
{
cleanup_executeCommand();
return env->NewStringUTF(result.c_str());
}
}
cleanup_executeCommand();
throw_executeCommand(env,"java/lang/Exception","err");
return env->NewStringUTF("");

C - Verify code signatures - Windows API

I need to verify code signatures of binaries. Microsoft Authenticode I think is the term. Is there a sane way to do this using the Windows API?
Have you looked at WinVerifyTrust ? Since it's not immediately obvious how to use it to verify the signature of a binary, you probably want to look at the sample code specifically for that.
How to find authenticode for drivers:
Disclaimer: I did not write this code.
BOOL VerifyEmbeddedSignature(LPCWSTR pwszSourceFile)
{
LONG lStatus;
GUID WintrustVerifyGuid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
GUID DriverActionGuid = DRIVER_ACTION_VERIFY;
HANDLE hFile;
DWORD dwHash;
BYTE bHash[100];
HCATINFO hCatInfo;
HCATADMIN hCatAdmin;
WINTRUST_DATA wd = { 0 };
WINTRUST_FILE_INFO wfi = { 0 };
WINTRUST_CATALOG_INFO wci = { 0 };
////set up structs to verify files with cert signatures
memset(&wfi, 0, sizeof(wfi));
wfi.cbStruct = sizeof( WINTRUST_FILE_INFO );
wfi.pcwszFilePath = pwszSourceFile;
wfi.hFile = NULL;
wfi.pgKnownSubject = NULL;
memset(&wd, 0, sizeof(wd));
wd.cbStruct = sizeof( WINTRUST_DATA );
wd.dwUnionChoice = WTD_CHOICE_FILE;
wd.pFile = &wfi;
wd.dwUIChoice = WTD_UI_NONE;
wd.fdwRevocationChecks = WTD_REVOKE_NONE;
wd.dwStateAction = 0;
wd.dwProvFlags = WTD_SAFER_FLAG;
wd.hWVTStateData = NULL;
wd.pwszURLReference = NULL;
wd.pPolicyCallbackData = NULL;
wd.pSIPClientData = NULL;
wd.dwUIContext = 0;
lStatus = WinVerifyTrust( NULL, &WintrustVerifyGuid, &wd );
////if failed, try to verify using catalog files
if (lStatus != ERROR_SUCCESS)
{
//open the file
hFile = CreateFileW(pwszSourceFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return FALSE;
dwHash = sizeof(bHash);
if (!CryptCATAdminCalcHashFromFileHandle(hFile, &dwHash, bHash, 0))
{
CloseHandle(hFile);
return FALSE;
}
//Create a string form of the hash (used later in pszMemberTag)
LPWSTR pszMemberTag = new WCHAR[dwHash * 2 + 1];
for ( DWORD dw = 0; dw < dwHash; ++dw )
{
wsprintfW( &pszMemberTag[dw * 2], L"%02X", bHash[dw] );
}
if (!CryptCATAdminAcquireContext(&hCatAdmin, &DriverActionGuid, 0))
{
CloseHandle(hFile);
return FALSE;
}
//find the catalog which contains the hash
hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin, bHash, dwHash, 0, NULL);
if ( hCatInfo )
{
CATALOG_INFO ci = { 0 };
CryptCATCatalogInfoFromContext( hCatInfo, &ci, 0 );
memset(&wci, 0, sizeof(wci));
wci.cbStruct = sizeof( WINTRUST_CATALOG_INFO );
wci.pcwszCatalogFilePath = ci.wszCatalogFile;
wci.pcwszMemberFilePath = pwszSourceFile;
wci.pcwszMemberTag = pszMemberTag;
memset(&wd, 0, sizeof(wd));
wd.cbStruct = sizeof( WINTRUST_DATA );
wd.dwUnionChoice = WTD_CHOICE_CATALOG;
wd.pCatalog = &wci;
wd.dwUIChoice = WTD_UI_NONE;
wd.fdwRevocationChecks = WTD_STATEACTION_VERIFY;
wd.dwProvFlags = 0;
wd.hWVTStateData = NULL;
wd.pwszURLReference = NULL;
wd.pPolicyCallbackData = NULL;
wd.pSIPClientData = NULL;
wd.dwUIContext = 0;
lStatus = WinVerifyTrust( NULL, &WintrustVerifyGuid, &wd );
CryptCATAdminReleaseCatalogContext( hCatAdmin, hCatInfo, 0 );
}
CryptCATAdminReleaseContext( hCatAdmin, 0 );
delete[] pszMemberTag;
CloseHandle(hFile);
}
if (lStatus != ERROR_SUCCESS)
return false;
else
return true;
}
Here is the working code to verify a file (technically any file type).
#include <stdio.h>
#include <windows.h>
#include <Softpub.h>
#include <wincrypt.h>
#include <wintrust.h>
#include <mscat.h>
#include <atlbase.h>
// Link with the Wintrust.lib file.
#pragma comment (lib, "wintrust")
BOOL VerifySignature(LPCSTR path) //We will receive the char* filepath not wchar*
{
USES_CONVERSION;
LPCWSTR pwszSourceFile = A2W(path); //We convert the char* to wchar*
LONG lStatus;
GUID WintrustVerifyGuid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
GUID DriverActionGuid = DRIVER_ACTION_VERIFY;
HANDLE hFile;
DWORD dwHash;
BYTE bHash[100];
HCATINFO hCatInfo;
HCATADMIN hCatAdmin;
WINTRUST_DATA wd = { 0 };
WINTRUST_FILE_INFO wfi = { 0 };
WINTRUST_CATALOG_INFO wci = { 0 };
////set up structs to verify files with cert signatures
wfi.cbStruct = sizeof(WINTRUST_FILE_INFO);
wfi.pcwszFilePath = pwszSourceFile;
wfi.hFile = NULL;
wfi.pgKnownSubject = NULL;
wd.cbStruct = sizeof(WINTRUST_DATA);
wd.pPolicyCallbackData = NULL;
wd.pSIPClientData = NULL;
wd.dwUIChoice = WTD_UI_NONE;
wd.fdwRevocationChecks = WTD_REVOKE_NONE;
wd.dwUnionChoice = WTD_CHOICE_FILE;
wd.pFile = &wfi;
wd.dwStateAction = WTD_STATEACTION_VERIFY;
wd.hWVTStateData = NULL;
wd.pwszURLReference = NULL;
wd.dwProvFlags |= WTD_CACHE_ONLY_URL_RETRIEVAL;
wd.dwUIContext = 0;
wd.pSignatureSettings = 0;
lStatus = WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &WintrustVerifyGuid, &wd);
wd.dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &WintrustVerifyGuid, &wd); //close hWVTStateData
////if failed, try to verify using catalog files
if (lStatus != ERROR_SUCCESS)
{
//open the file
hFile = CreateFileW(pwszSourceFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return FALSE;
dwHash = sizeof(bHash);
if (!CryptCATAdminCalcHashFromFileHandle(hFile, &dwHash, bHash, 0))
{
CloseHandle(hFile);
return FALSE;
}
//Create a string form of the hash (used later in pszMemberTag)
LPWSTR pszMemberTag = new WCHAR[dwHash * 2 + 1];
for (DWORD dw = 0; dw < dwHash; ++dw)
{
wsprintfW(&pszMemberTag[dw * 2], L"%02X", bHash[dw]);
}
if (!CryptCATAdminAcquireContext(&hCatAdmin, &DriverActionGuid, 0))
{
CloseHandle(hFile);
return FALSE;
}
//find the catalog which contains the hash
hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin, bHash, dwHash, 0, NULL);
if (hCatInfo)
{
CATALOG_INFO ci = { 0 };
CryptCATCatalogInfoFromContext(hCatInfo, &ci, 0);
memset(&wci, 0, sizeof(wci));
wci.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
wci.pcwszCatalogFilePath = ci.wszCatalogFile;
wci.pcwszMemberFilePath = pwszSourceFile;
wci.hMemberFile = hFile;
wci.pcwszMemberTag = pszMemberTag;
wci.pbCalculatedFileHash = bHash;
wci.cbCalculatedFileHash = dwHash;
wci.hCatAdmin = hCatAdmin;
memset(&wd, 0, sizeof(wd));
wd.cbStruct = sizeof(WINTRUST_DATA);
wd.pPolicyCallbackData = NULL;
wd.pSIPClientData = NULL;
wd.dwUIChoice = WTD_UI_NONE;
wd.fdwRevocationChecks = WTD_REVOKE_NONE;
wd.dwUnionChoice = WTD_CHOICE_CATALOG;
wd.pCatalog = &wci;
wd.dwStateAction = WTD_STATEACTION_VERIFY;
wd.hWVTStateData = NULL;
wd.pwszURLReference = NULL;
wd.dwProvFlags |= WTD_CACHE_ONLY_URL_RETRIEVAL;
wd.dwUIContext = 0;
wd.pSignatureSettings = 0;
lStatus = WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &WintrustVerifyGuid, &wd);
wd.dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &WintrustVerifyGuid, &wd); //close hWVTStateData
CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
}
CryptCATAdminReleaseContext(hCatAdmin, 0);
delete[] pszMemberTag;
CloseHandle(hFile);
}
return (lStatus == ERROR_SUCCESS);
}
int main(int argc, char *argv[])
{
if (VerifySignature(argv[1]))
printf("Verified file signature\n");
else
printf("Could not verify file signature\n");
return 0;
}

Resources