ToUnicodeEx - Skip Keyboard Buffer - winapi

Analogous to my question on how to translate a System.Windows.Forms.Keys set to a System.Char
I'm trying to convert a Virtual-Key Code to a character with ToUnicodeEx
Some keys become dead-key characters which are stored in a buffer for the next call (ToUnicodeEx returing -1), an other times one of them is already stored there.
But I want to skip that buffer and my program should not affect/be affected from it.
Is there a way for what I need?
(So: If my virtual-key code translates to a dead-key, it should not remain in the buffer, and if there is a dead-key in the buffer, it should not change my current function call)

Related

Why does SetFilePointerEx(1) succeed for an empty file that's open for reading only?

I do not understand why the following code, which sets the position of an open file handle relative to the base (i. e. sets the absolute position) succeeds when trying to set a positive position for an empty file that's open for reading only:
LARGE_INTEGER offset;
offset.QuadPart = 100;
LARGE_INTEGER pos = {0};
return ::SetFilePointerEx(_h, offset, &pos, FILE_BEGIN) != 0;
It returns a non-zero result, and the pos variable receives the value 100. That behavior is counter-intuitive for a GENRIC_READ file of size zero, what is the logic? I understand that this is normal behavior for files with write access.
P. S. The file is not overlapped and overall as simple as it can be with no fancy flags.
Does SetFilePointerEx ever fail at all for valid handles, positive absolute positions and plain files?
SetFilePointerEx internally call ZwSetInformationFile with FilePositionInformation. the FILE_POSITION_INFORMATION used as input.
exist only such restriction on this value
If the file was opened or created with the
FILE_NO_INTERMEDIATE_BUFFERING option, the value of CurrentByteOffset
must be an integral multiple of the sector size of the underlying
device.
also, always must be 0 <= CurrentByteOffset.QuadPart- so position must be not negative.
no more restriction on position value. you can set it to any, not depend from file size. this call even never go to file system but handle by I/O manager.
all what he doing - set CurrentByteOffset in FILE_OBJECT
how this is used ? when we call ZwReadFile or ZwWriteFile - the optional parameter ByteOffset exist
Pointer to a variable that specifies the starting byte offset in the
file where the read operation will begin. If an attempt is made to
read beyond the end of the file, ZwReadFile returns an error.
If the call to ZwCreateFile set either of the CreateOptions flags
FILE_SYNCHRONOUS_IO_ALERT or FILE_SYNCHRONOUS_IO_NONALERT, the I/O
Manager maintains the current file position. If so, the caller of
ZwReadFile can specify that the current file position offset be used
instead of an explicit ByteOffset value. This specification can be
made by using one of the following methods:
Specify a pointer to a LARGE_INTEGER value with the HighPart member
set to -1 and the LowPart member set to the system-defined value
FILE_USE_FILE_POINTER_POSITION.
Pass a NULL pointer for ByteOffset.
ZwReadFile updates the current file position by adding the number of
bytes read when it completes the read operation, if it is using the
current file position maintained by the I/O Manager.
Even when the I/O Manager is maintaining the current file position,
the caller can reset this position by passing an explicit ByteOffset
value to ZwReadFile. Doing this automatically changes the current file
position to that ByteOffset value, performs the read operation, and
then updates the position according to the number of bytes actually
read. This technique gives the caller atomic seek-and-read service.
so we can or explicit pass ByteOffset value or use additional api call for set it first in FILE_OBJECT and then I/O manager take it from here, if no explicit ByteOffset pointer.
note - in case asynchronous I/O - we need always explicit pass ByteOffset value or call just fail (exception for pipes and mailslot files)
in case ReadFile and WriteFile - ByteOffset taken from OVERLAPPED parameter. if it is 0 - the ByteOffset set to 0 pointer and CurrentByteOffset from FILE_OBJECT is used. and if pointer to OVERLAPPED not 0 - the exactly value from OVERLAPPED is explicit passed as ByteOffset value and CurrentByteOffset in FILE_OBJECT is ignored.
also always is ok use pointer to OVERLAPPED - not only for asynchronous file handles. simply for asynchronous - this is mandatory parameter and for synchronous is optional.
really faster and better - direct pass pointer to api call (read/write) than use separate api call, which take time, can (theoretical) fail, etc
use SetFilePointer may be exist sense only in legacu code, where it called from huge count of places, for not modify too many code

ReadFile truncating console input data containing multibyte characters, how to get correct input?

I was trying to implement a unified input interface using Windows API function ReadFile for my application, which should be able to handle both console input and redirection. It didn't work as expected with console input containing multibyte (like CJK) characters.
According to Microsoft Documentation, for console input handles, ReadFile just behaves like ReadConsoleA. (FYI, results are encoded in console's current code page, so A family console functions are acceptable. And there's no ReadFileW as ReadFile works on bytes.) The third and fourth arguments in ReadFile is nNumberOfBytesToRead and lpNumberOfBytesRead respectively, but they are nNumberOfCharsToRead and lpNumberOfCharsRead in ReadConsole. To find out the exact mechanism, I did the following test:
BYTE buf[8];
DWORD len;
BOOL f = ReadFile(in, buf, 4, &len, NULL);
if (f) {
// Print buf, len
ReadConsoleW(in, buf, 4, &len, NULL); // check count of remaining characters
// Print len
}
For input like 字, len is set to 4 first (character plus CRLF), indicating the arguments are counting bytes.
For 文字 or a字, len keeps 4 and only the first 4 bytes of buf are used at first, but the second read does not get the CRLF. Only when more than 3 characters are input will the second read get unread LF, then CR. It means that ReadFile is actually consuming up to 4 logical characters, and discarding the part of input after the first 4 bytes.
The behavior of ReadConsoleA is identical to ReadFile.
Obviously, this is more likely to be a bug than design. I did some searches and found a related feedback dating back to 2009. It seems that ReadConsoleA and ReadFile did read data fully from console input, but as it was inconsistent with ReadFile specifications and could cause severe buffer overflow that threatened system processes, Microsoft did a makeshift repair, by simply discarding excess bytes, ignoring support for multibyte charsets. (This is an issue about the behavior after that, limiting buffer to 1 byte.)
Currently the only practical solution I have come up with to make input correct is to check whether the input handle is a console, and process it differently using ReadConsoleW if so, which adds complexity to the implementation. Are there other ways to get it correct?
Maybe I could still keep ReadFile, by providing a buffer large enough to hold any input at one time. However, I don't have any ideas on how to check or set the input buffer size. (I can only enter 256 characters (254 plus CRLF) in my application on my computer, but cmd.exe allows to enter 8,192 characters, so this is really a problem.) It will also be helpful if more information about this can be provided.
Ps.: Maybe _getws could also help, but this question is about Windows API, and my application needs to use some low-level console functions.

Using SetFilePointer to change the location to write in the sector doesn't work?

I'm using SetFilePointer to rewrite the second half of the MBR with something, its a user-mode application and i opened a handle to PhysicalDrive
At first i tried to set the size parameter in WriteFile to 256 but the writefile gave the INVALID_PARAMETER error, as it turns out based on some search on other questions here it seems like this is because we are forced to write in multiplicand of the sector size when the handle is PhysicalDrive for some reason
then i tried to set the filePointer to 256, and Write 512 bytes, both of them return no error, but for some unknown reason it writes from the beginning of the sector! as if the SetFilePointer didn't work even tho the return value of SetFilePointer is OK and it returns 256
So my questions is :
Why the write size have to be multiplicand of sector size when the handle is PhysicalDrive? which other device handles are like this?
Why is this happening and when I set the file pointer to 256, WriteFile still writes from the start?
isn't this really redundant, considering that even if I want to change 1 byte then I have to read the entire sector, change the one byte and then write it back, instead of just writing 1 byte, it seems like 10 times more overhead! isn't there a faster way to write a few bytes in a sector?
I think you are mixing the file system and the storage (block device). File system stays above storage device stack. If your code obtains a handle to a file system device, you can write byte by byte. But if you are accessing storage device stack, you can only write sector by sector (or block size).
Directly writing to block device is definitely slow as you discovered. However, in most cases, people just talk to file systems. Most file system drivers maintain cache and use algorithms for both read and write to improve performance.
Can't comment on file pointer based offset before seeing the actual code. But I guess it might be not sector aligned or it's not used at all.

writing partial data with libwebsockets

I'm using the libwebsockets v2.4.
The doc seems unclear to me about what I have to do with the returned value of the lws_write() function.
If it returns -1, it's an error and I'm invited to close the connection. That's fine for me.
But when it returns a value that is strictly inferior to the buffer length I pass, should I consider that I have to write the last bytes that could not be written later (in another WRITABLE callback occurrence). Is it even possible to have this situation?
Also, should I use the lws_send_pipe_choked() before using the lws_write(), considering that I always use lws_write() in the context of a WRITABLE callback?
My understanding is that lws_write always return the asked buffer length except is an error occurs.
If you look at lws_issue_raw() (from which the result is returned by lws_write()) in output.c (https://github.com/warmcat/libwebsockets/blob/v2.4.0/lib/output.c#L157), you can see that if the length written by lws_ssl_capable_write() is less than the provided length, then the lws allocate a buffer to fill up the remaining bytes on wsi->trunc_alloc, in order for it to be sent in the future.
Concerning your second question, I think it is safe to call lws_write() in the context of a WRITABLE callback without checking if the pipe is choked. However, if you happen to loop on lws_write() in the callback, lws_send_pipe_choked() must be called in order to protect the subsequent calls to lws_write(). If you don't, you might stumble upon this assertion https://github.com/warmcat/libwebsockets/blob/v2.4.0/lib/output.c#L83 and the usercode will crash.

Example to store pointer in extra window memory of window class

I have a class that represents a text box, in the constructor of the class I call the CreateWindow function, and I want to store in the extra window memory, pointer to this object, so in the WndProc function I will get the pointer, and will use the class members.
I tried to do that with this code, but it's not working, can someone to write an example how to do this:
What value should I give in cbWndExtra member of WNDCLASSEX structure.
How to call SetWindowLong.
How to call GetWindowLong.
the code I wrote:
wcex.cbWndExtra = 4;
and I wrote this in the constructor of the text box class:
hWnd = CreateWindow(...);
SetWindowLong(hWnd,0,(LONG)this);
and this in the WndProc function
unique_ptr<TextBox> pTextBox;
pTextBox.reset((TextBox*)GetWindowLong(hWnd,0));
=== edit ===
now I see that if I change the code in the WndProc function, to this code:
TextBox *pTextBox;
pTextBox = (TextBox*)GetWindowLong(hWnd,0);
it work as well, but with unique_ptr it do not work.
From the MSDN Documentation on "SetWindowLong", about the 'Index' parameter.
The zero-based offset to the value to be set. Valid values are in the range zero through the number of bytes of extra window memory, minus the size of an integer. To set any other value, specify one of the following values.
Positive offsets can point to any byte offset so long as you created the window with at least that amount of "cbWndExtra" in the WNDCLASS structure.
I suspect the issue in this case may be related to the size of the pointer. You are explicitly allocating 4 extra bytes to the end of the window structure, but if you are on a 64-bit system, the pointer size would be 8. This could explain it sometimes working, and sometimes not. (If the high order word happens to be all zeros, it may work even though the address is being truncated.)
If this is the case, you would need to either set the high and low word in two separate calls, or preferably use the 64-bit variant "SetWindowLongPtr".
Here's a simple example that uses this feature to store two pointers in a windows extra data region (Note the following will work with both 32 and 64 bit)
wndclass.cbWndExtra = sizeof(char*) * 2; // Reserve space for 2 pointers.
Then later set a values with:
SetWindowLongPtr(hwnd, 0, (LONG_PTR)firstPtr);
SetWindowLongPtr(hwnd, sizeof(char*), (LONG_PTR)secondPtr); // Index is byte offset.
And retrieve the values with:
LONG_PTR firstPtr = GetWindowLongPtr(hwnd, 0);
LONG_PTR secondPtr = GetWindowLongPtr(hwnd, sizeof(char*));
If you only need to store one single pointer however, you can get away with not setting any extra memory, leave cbWndExtra at zero, and just pass GWLP_USERDATA as the index. Like the other pre-defined values, GWLP_USERDATA is a negative offset 'backwards' into the class/window data. It is reserved space for this kind of purpose, but it can only fit one pointers worth of data.

Resources