using writeprivateprofilestringw and readprivateprofilestringw in unicode not working - c

I try to write a push-pop like program using Read/WriteprivateprofilestringW functions and there are problems I don’t think I can see by myself. If you are kind please have a look at my lines and point me so I get it to run correctly.
When I run it with an already created file, the output of writeprivateprofilestringw's section field name is wrong. I think it’s because I’m using LPWSTR data type but nothing I tried solves it.
output:
[win32 app\Release\fonemeW.dic]
dictsionar=dicţionar
expected output:
[dictionar]
dictsionar=dicţionar
////////////////////////////////////////////////////////////////////////
//
// push word into dictionary
//
////////////////////////////////////////////////////////////////////////
void pushWordW(LPWSTR szWord, LPWSTR szFonems){
WCHAR* szDic=(WCHAR)calloc(MAX_PATH, sizeof(WCHAR));
LPWSTR sztemp=L"dictionar";
wcscpy(szDic, L"fonemeW.txt");
getDicFile(&szDic);
WritePrivateProfileStringW(L"dictionar", szFonems, szWord, szDic);
}
////////////////////////////////////////////////////////////////////////
//
// pull word from the dictionary as query fonem string
//
///////////////////////////////////////////////////////////////////////
void pullWordW(TCHAR* szWord[MAX_PATH], LPWSTR szFonems){
WCHAR* szDic=(WCHAR)calloc(MAX_PATH, sizeof(WCHAR));
wcscpy(szDic, L"fonemeW.dic");
getDicFile(&szDic);
GetPrivateProfileStringW(L"dictionar", szFonems, L"", szWord[0], 0, szDic);
if(wcslen(szWord[0])==0)
MessageBox(0, "Word not in the dictionar", "titlu popWordW", 0);
}
////////////////////////////////////////////////////////////////////////
//
// test the push-pop (from the dictionary) procedures
//
////////////////////////////////////////////////////////////////////////
void testPP(void){
LPWSTR szWord=L"dictionar";
szWord[3]=0x0163;
LPWSTR szFonem=L"dictsionar";
MessageBoxW(0, szWord, L"titlu testPP", 0);
pushWordW(szWord, szFonem);//push word into dictionar
wcscpy(szFonem, L"diade-muh");//query dictionar
pullWordW(&szWord, szFonem);//pop word from dictionary based on fonem transliteration
MessageBoxW(0, szWord, L"titlu testPP", 0);
}
edit i editted the declaration of szWord and there seems to be no problems anymore.

You did not show the implementation for getDicFile(), so I can only assume it works correctly (though the code will leak memory if getDicFile() returns a pointer to dynamically allocated memory).
I don't see any problem with the implementation of your pushWordW() function. It should not be using a filename as the INI section name. So this implies that you are actually passing an incorrect/corrupted pointer to the lpAppName parameter of WritePrivateProfileString().
However, I do see problems with the implementation of your pullWordW() and testPP() functions.
in testPP(), szWord initially points to a string literal, which is read-only. Thus, the statement szWord[3]=0x0163; should have caused a run-time error trying to write to read-only memory. So, either change the literal to L"dicţionar" so you do not need szWord[3]=0x0163; anymore, or else change the declaration of szWord to WCHAR[] instead of LPWSTR, or use malloc(), to allocate writable memory that the literal can then be copied into (in the latter case, don't forget to free() it when you are done using it).
in testPP(), szFonem initially points to a read-only string literal as well. Thus, the statement wcscpy(szFonem, L"diade-muh"); should similarly be causing a run-time error trying to write to read-only memory.
when testPP() calls pullWordW(), passing szWord using the & operator implies that pullWordW() is expected to update szWord with a new memory address pointing at the data returned by GetPrivateProfileStringW(). The problem is, GetPrivateProfileStringW() expects a pre-allocated buffer of writable memory to store the data into, but the pointer you are actually passing to it is a pointer to the read-only literal that szWord was initially set to. Again, it should be causing a run-time error. But it actually won't, because you are setting the nSize parameter of GetPrivateProfileStringW() to 0, telling it that there is no space available at the memory address for it to store data into. So no run-time errror. But, let's just say for the sake of argument that it could write data. pullWordW() is not updating its szWord parameter to point at any new memory address. And even if it did, who is responsible for allocating that memory, and who is responsible for freeing it? Your code is not defining those rules anywhere.
The fact that you are not encountering run-time errors that crash your app likely means that memory is being corrupted instead, in which case all bets are off.
Fix your code to use memory correctly. For example:
////////////////////////////////////////////////////////////////////////
//
// get dictionary filename
//
////////////////////////////////////////////////////////////////////////
bool getDicFile(LPWSTR szDic, int nDic){
// copy whatever your actual dictionary filename is...
return (wcscpy_s(szDic, nDic, L"fonemeW.dic") == 0);
}
////////////////////////////////////////////////////////////////////////
//
// push word into dictionary
//
////////////////////////////////////////////////////////////////////////
void pushWordW(LPWSTR szWord, LPWSTR szFonems){
WCHAR szDic[MAX_PATH+1];
if (getDicFile(szDic, MAX_PATH+1)){
WritePrivateProfileStringW(L"dictionar", szFonems, szWord, szDic);
}
}
////////////////////////////////////////////////////////////////////////
//
// pull word from the dictionary as query fonem string
//
///////////////////////////////////////////////////////////////////////
bool pullWordW(LPWSTR szWord, int nWord, LPWSTR szFonems){
LPWSTR szDic[MAX_PATH+1];
if (getDicFile(szDic, MAX_PATH+1)){
return (GetPrivateProfileStringW(L"dictionar", szFonems, L"", szWord, nWord, szDic) > 0);
}
return false;
}
////////////////////////////////////////////////////////////////////////
//
// test the push-pop (from the dictionary) procedures
//
////////////////////////////////////////////////////////////////////////
void testPP(void){
WCHAR szWord[256] = L"dictionar";
szWord[3]=0x0163;
WCHAR szFonem[12] = L"dictsionar";
MessageBoxW(0, szWord, L"titlu testPP", 0);
pushWordW(szWord, szFonem);//push word into dictionar
wcscpy_s(szFonem, 12, L"diade-muh");//query dictionar
if (pullWordW(szWord, 256, szFonem)){//pop word from dictionary based on fonem transliteration
MessageBoxW(0, szWord, L"titlu testPP", 0);
} else {
MessageBoxW(0, L"Word not in the dictionar", L"titlu popWordW", 0);
}
}

Related

c will a const *char function memory leak? [duplicate]

I am using json-c library to send json-object to client.And I notice there is no native function to release the memory which json_object_to_json_string allocate.Does the library release it automaticlly? OR I have to "free(str)" to avoid memory leak?
I tried to read its source code but it makes me unconscious...So anybody know this?
It seems that you don't need to free it manually.
I see that this buffer comes from within the json_object (see the last line of this function):
const char* json_object_to_json_string_ext(struct json_object *jso, int flags)
{
if (!jso)
return "null";
if ((!jso->_pb) && !(jso->_pb = printbuf_new()))
return NULL;
printbuf_reset(jso->_pb);
if(jso->_to_json_string(jso, jso->_pb, 0, flags) < 0)
return NULL;
return jso->_pb->buf;
}
The delete function frees this buffer:
static void json_object_generic_delete(struct json_object* jso)
{
#ifdef REFCOUNT_DEBUG
MC_DEBUG("json_object_delete_%s: %p\n",
json_type_to_name(jso->o_type), jso);
lh_table_delete(json_object_table, jso);
#endif /* REFCOUNT_DEBUG */
printbuf_free(jso->_pb);
free(jso);
}
It is important to understand that this buffer is only valid while the object is valid. If the object reaches 0 reference count, the string is also freed and if you are using it after it is freed the results are unpredictable.

How to get the class name of a window with C

Objective: Retrieve the class name of the current foreground window with plain C.
I have the following code to retrieve the class name:
PWSTR win_class = NULL;
GetClassNameW(hwnd,&win_class,MAX_PATH);
if(win_class != NULL)
free(win_class);
I am getting the following warnings:
warning C4047: 'function': 'LPWSTR' differs in levels of indirection
from 'PWSTR *' warning C4024: 'GetClassNameW': different types
for formal and actual parameter 2
I have two questions: How to solve those warnings, and how should I create an if condition to validate the result of the function GetClassName and set the value of win_class to "NOT FOUND" in case that the function does not find the class name?
The GetClassNameW() function does not allocate the memory needed for the returned class name - you have to do that (or simply provide automatic storage).
To check for success, simply test the return value of the function: if it succeeds, that will be the length of the class name string (in characters); if it fails, the value will be zero.
Here's a short, runnable program that gets the class name for the console window:
#include <Windows.h>
#include <stdio.h>
int main()
{
HWND hwnd = GetConsoleWindow();
wchar_t win_class[_MAX_PATH];
int status = GetClassNameW(hwnd, win_class, _MAX_PATH);
if (!status) wcscpy(win_class, L"NOT FOUND");
printf("%ls\n", win_class);
return 0;
}
When calling GetClassNameW(), you are passing a PWSTR* (wchar_t**) where a LPWSTR (wchar_t*) is expected. That is what the compiler is complaining about.
GetClassName() requires you to pre-allocate a character buffer and pass in a pointer to it, along with the buffer size. The function will not allocate a buffer and return a pointer back to you, like you are expecting. It will merely fill in your provided buffer as needed.
Try something more like this:
WCHAR win_class[256] = {0};
int win_class_len = 0;
HWND hwnd = GetForegroundWindow();
if (!hwnd)
{
// error handling as needed...
lstrcpyW(win_class, L"WINDOW NOT FOUND");
win_class_len = lstrlenW(win_class);
}
else
{
win_class_len = GetClassNameW(hwnd, win_class, 256);
if (win_class_len == 0)
{
DWORD err = GetLastError();
// error handling as needed...
lstrcpyW(win_class, L"CLASS NOT FOUND");
win_class_len = lstrlenW(win_class);
}
}
// use win_class as needed, up to win_class_len characters...
TCHAR is the universal char type working for Unicode and ANSI. GetClassName is the corresponding function replaced with GetClassNameA or GetClassNameW. If you need static string use TEXT() macro like TCHAR * s = TEXT("abc");
TCHAR win_class[MAX_PATH];
int res = GetClassName( hwnd, win_class, MAX_PATH );
if ( res > 0 )
// success
Your error is that win_class was unallocated (NULL) string pointer. GetClassName needs valid memory address of buffer.
You need to check if you function succseed. To do so, print the return value of the function.
Failiure will be presented by the value 0.

getting a list of kernel objects windows

HI!
I bet more than a week and I can not form a complete picture of how you can get a list of kernel objects .My algorithm is as follows :
1) Connecting NTDLL.dll (LoadLibrary)
2) GetProcAddress (variable_Library_name, "NtQueryDirectoryObject")
and the pre-announcement structures : _OBJDIR_INFORMATION,
_OBJECT_ATTRIBUTES
3) Trying to apply a function NtOpenDirectoryObject for a list of
objects
Here is a piece of code that is responsible for the use of the function NtOpenDirectoryObject:
OBJDIR_INFORMATION *ssinfo =(OBJDIR_INFORMATION* ) HeapAlloc(GetProcessHeap(), 0, 0x800);
///////////////////////
HANDLE hFile,hThread,hMapFile;
HMODULE hNtdll ,hKernel;
DWORD dwThreadId;
OBJECT_ATTRIBUTES obj;
WCHAR * uString=L"\\BaseNamedObjects";
UNICODE_STRING str;
DWORD i,a,iStrLen,b=0;
char sObjName[30],sTmp[50];
LPVOID lpMapAddress;
FARPROC pWinExec,pExitThread;
bool bFound;
char* sCommand;
/////////////////////////////////////////////////////////////////
NtQueryDirectoryObject = (NTQUERYDIRECTORYOBJECT )GetProcAddress(hinstLib,"NtQueryDirectoryObject");
InitializeObjectAttributes (&obj, &str, 0, 0, 00);
NtOpenDirectoryObject(&hFile,0x20001,&obj);
The full code (including struct definitions) is at: http://pastebin.com/pDNb3GTn
When calling a function with parameters NtOpenDirectoryObject get an exception c0000005, which means that access is blocked .
tell me please, am I doing smth wrong, and where is my mistake. Is it possible to not to use the native api? Thank you for your help
Exception c0000005 is an Access Violation. That does not mean that access was blocked. It means invalid memory was accessed, such as if a NULL/uninitialized pointer were accessed, or if you are not aligning data correctly and accessing something out of bounds of what you have allocated.
As Andrew mentioned, you are not initializing the UNICODE_STRING at all. Try this instead:
hNtdll = LoadLibrary("ntdll.dll");
NtOpenDirectoryObject = (NTOPENDIRECTORYOBJECT) GetProcAddress(hNtdll, "NtOpenDirectoryObject");
...
if (NtOpenDirectoryObject)
{
// add these three lines
str.Length = lstrlenW(uString) * sizeof(WCHAR);
str.MaximumLength = str.Length;
str.Buffer = uString;
InitializeObjectAttributes (&obj, &str, 0, NULL, NULL);
NtOpenDirectoryObject(&hFile, 0x20001, &obj);
}

TCL_LINK_STRING causing segmentation fault (core dumped)

I'm trying to share a variable with c and tcl, the problem is when i try to read the variable in the c thread from tcl, it causes segmentation error, i'm not sure this is the right way to do it, but it seems to work for ints. The part that is causing the segmentation fault is this line is when i try to print "Var" but i want to read the variable to do the corresponding action when the variable changes.
Here is the C code that i'm using
void mode_service(ClientData clientData) {
while(1) {
char* Var = (char *) clientData;
printf("%s\n", Var);
usleep(100000); //100ms
}
}
static int mode_thread(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
Tcl_ThreadId id;
ClientData limitData;
limitData = cdata;
id = 0;
Tcl_CreateThread(&id, mode_service, limitData, TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS);
printf("Tcl_CreateThread id = %d\n", (int) id);
// Wait thread process, before returning to TCL prog
int i, aa;
for (i=0 ; i<100000; i++) {aa = i;}
// Return thread ID to tcl prog to allow mutex use
Tcl_SetObjResult(interp, Tcl_NewIntObj((int)id));
printf("returning\n");
return TCL_OK;
}
int DLLEXPORT Modemanager_Init(Tcl_Interp *interp){
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
if (Tcl_PkgProvide(interp, "PCIe", "1.0") == TCL_ERROR) {
return TCL_ERROR;
}
// Create global Var
int *sharedPtr=NULL;
//sharedPtr = sharedPtr = (char *) Tcl_Alloc(sizeof(char));
Tcl_LinkVar(interp, "mode", (char *) &sharedPtr, TCL_LINK_STRING);
Tcl_CreateObjCommand(interp, "mode_thread", mode_thread, sharedPtr, NULL);
return TCL_OK;
}
In the tcl code, i'm changing the variable mode whenever the user presses a button for example:
set mode "Idle"
button .startSamp -text "Sample Start" -width 9 -height 3 -background $btnColor -relief flat -state normal -command {set mode "Sampling"}
set threadId [mode_thread]
puts "Created thread $threadId, waiting"
Your code is a complete mess! You need to decide what you are doing and then do just that. In particular, you are using Tcl_LinkVar so you need to decide what sort of variable you are linking to. If you get a mismatch between the storage, the C access pattern and the declared semantic type, you'll get crashes.
Because your code is in too complicated a mess for me to figure out exactly what you want to do, I'll illustrate with less closely related examples. You'll need to figure out from them how to change things in your code to get the result you need.
Linking Integer Variables
Let's do the simple case: a global int variable (declared outside any function).
int sharedVal;
You want your C code to read that variable and get the value. Easy! Just read it as it is in scope. You also want Tcl code to be able to write to that variable. Easy! In the package initialization function, put this:
Tcl_LinkVar(interp /* == the Tcl interpreter context */,
"sharedVal" /* == the Tcl name */,
(char *) &sharedVal /* == pointer to C variable */,
TCL_LINK_INT /* == what is it! An integer */);
Note that after that (until you Tcl_UnlinkVar) whenever Tcl code reads from the Tcl variable, the current value will be fetched from the C variable and converted.
If you want that variable to be on the heap, you then do:
int *sharedValPtr = malloc(sizeof(int));
C code accesses using *sharedValPtr, and you bind to Tcl with:
Tcl_LinkVar(interp /* == the Tcl interpreter context */,
"sharedVal" /* == the Tcl name */,
(char *) sharedValPtr /* == pointer to C variable */,
TCL_LINK_INT /* == what is it! An integer */);
Linking String Variables
There's a bunch of other semantic types as well as TCL_LINK_INT (see the documentation for a list) but they all follow that pattern except for TCL_LINK_STRING. With that, you do:
char *sharedStr = NULL;
Tcl_LinkVar(interp, "sharedStr", (char *) &sharedStr, TCL_LINK_STRING);
You also need to be aware that the string will always be allocated with Tcl_Alloc (which is substantially faster than most system memory allocators for typical Tcl memory usage patterns) and not with any other memory allocator, and so will also always be deallocated with Tcl_Free. Practically, that means if you set the string from the C side, you must use Tcl_Alloc to allocate the memory.
Posting Update Notifications
The final piece to note is when you set the variable from the C side but want Tcl to notice that the change has set (e.g., because a trace has been set or because you've surfaced the value in a Tk GUI), you should do Tcl_UpdateLinkedVar to let Tcl know that a change has happened that it should pay attention to. If you never use traces (or Tk GUIs, or the vwait command) to watch the variable for updates, you can ignore this API call.
Donal's answer is correct, but I try to show you what you did with your ClientData.
To clarify: All (or almost all, Idk) Tcl functions that take a function pointer also take a parameter of type ClientData that is passed to your function when Tcl calls it.
Let's take a look at this line:
Tcl_CreateObjCommand(interp, "mode_thread", mode_thread, NULL, NULL);
// ------------------------------------------------------^^^^
You always pass NULL as ClientData to the mode_thread function.
In the mode_thread function you use the passed ClientData (NULL) to pass it as ClientData to the new Thread:
limitData = cdata;
// ...
Tcl_CreateThread(&id, mode_service, limitData, TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS);
In the mode_service function you use the ClientData (which is still NULL) as pointer to a char array:
char* Var = (char *) clientData;
Which is a pointer to the address 0x00.
And then you tell printf to dereference this NULL pointer:
printf("%s\n", Var);
Which obviously crashes your program.

asynchronous serial port communication in windows in c

I am getting an error when I try to run a c file which does some basic writes to a serial port. I am trying to run it asynchronously because the writes sometimes take a long time to transfer. My original version had it running synchronously with WriteFile() commands which worked fine. I am new to using OVERLAPPED and would appreciate and input concerning it.
The error I am getting is:
Debug Assertion Failed!
<path to dbgheap.c>
Line: 1317
Expression: _CrtIsValidHeapPointer(pUserData)
when the second write function is called.
In main:
{
//initialized port (with overlapped), DBC, and timeouts
result = write_port(outPortHandle, 128);
result = write_port(outPortHandle, 131);
}
static void CALLBACK write_compl(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) {
//write completed. check for errors? if so throw an exception maybe?
printf("write completed--and made it to callback function\n");
}
int write_port(HANDLE hComm,BYTE* lpBuf) {
OVERLAPPED osWrite = {0};
// Create this write operation's OVERLAPPED structure's hEvent.
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osWrite.hEvent == NULL)
// error creating overlapped event handle
return 0;
// Issue write.
if (!WriteFileEx(hComm, &lpBuf, 1, &osWrite, &write_compl )) {
if (GetLastError() != ERROR_IO_PENDING) {
// WriteFile failed, but isn't delayed. Report error and abort.
printf("last error: %ld",GetLastError());
return 0; //failed, return false;
}
else {
// Write is pending.
WaitForSingleObjectEx(osWrite.hEvent, 50, TRUE); //50 ms timeout
return -1; //pending
}
}
else {
return 1; //finished
}
}
That was not the full code, sorry. I was using an array of BYTEs as well, not constants. But system("pause")'s were causing my debug assertion failed errors, and after carefully looking through my code, when the WriteFileEx() was successful, it was never setting an alert/timeout on the event in the overlapped structure, so the callback function would never get called. I fixed these problems though.
I just need help with the handling/accessing a single BYTE in a structure which is allocated when a ReadFileEx() function is called (for storing the BYTE that is read so it can be handled). I need to know how to access that BYTE storage using an offset and make the overlapped structure null. Would making the overlapped structure null be as simple as setting the handle in it to INVALID_HANDLE_VALUE?
I think you have a couple of issues:
You are passing an integer as a pointer (your compiler should warn against this or preferably refuse to compile the code):
result = write_port(outPortHandle, 128);
Compare this to the definition of write_port:
int write_port(HANDLE hComm,BYTE* lpBuf) {
The above statements doesn't match. Later on you then pass a pointer to the lpBuf pointer to the WriteFileEx function by taking the address of the BYTE* -> "&lpBuf". This will not result in what you think it will do.
Even if you fix this, you will still have potential lifetime issues whenever the write is successfully queued but won't complete within the 50 ms timeout.
When using overlapped I/O, you need to make sure that the read/write buffer and the overlapped structure remain valid until the I/O is completed, cancelled or the associated device is closed. In your code above you use a pointer to an OVERLAPPED struct that lives on the stack in your call to WriteFileEx. If WriteFileEx does not complete within 50 ms, the pending I/O will have a reference to a non-existing OVERLAPPED struct and you will (hopefully) have an access violation (or worse, silently corrupted stack data somewhere in your app).
The canonical way of handling these lifetime issues (if performance is not a big issue), is to use a custom struct that includes an OVERLAPPED struct and some storage for the data to be read/written. Allocate the struct when posting the write and deallocate the struct from the I/O completion routine. Pass the address of the included OVERLAPPED struct to WriteFileEx, and use e.g. offsetof to get the address to the custom struct from the OVERLAPPED address in the completion routine.
Also note that WriteFileEx does not actually use the hEvent member, IIRC.
EDIT: Added code sample, please note:
I haven't actually tried to compile the code, there might be typos or other problems with the code.
It's not the most efficient way of sending data (allocating/deallocating a memory block for each byte that is sent). It should be easy to improve, though.
#include <stddef.h>
#include <assert.h>
#include <windows.h>
// ...
typedef struct _MYOVERLAPPED
{
OVERLAPPED ol;
BYTE buffer;
} MYOVERLAPPED, *LPMYOVERLAPPED;
// ...
static void CALLBACK write_compl(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
{
if (NULL == lpOverlapped)
{
assert(!"Should never happen");
return;
}
LPBYTE pOlAsBytes = (LPBYTE)lpOverlapped;
LPBYTE pMyOlAsBytes = pOlAsBytes - offsetof(MYOVERLAPPED, ol);
LPMYOVERLAPPED pMyOl = (LPMYOVERLAPPED)pOlAsBytes;
if ((ERROR_SUCCESS == dwErrorCode) &&
(sizeof(BYTE) == dwNumberOfBytesTransfered))
{
printf("written %uc\n", pMyOl->buffer);
}
else
{
// handle error
}
free(pMyOl);
}
int write_port(HANDLE hComm, BYTE byte) {
LPMYOVERLAPPED pMyOl = (LPMYOVERLAPPED)malloc(sizeof(MYOVERLAPPED));
ZeroMemory(pMyOl, sizeof(MYOVERLAPPED));
pMyOl->buffer = byte;
// Issue write.
if (!WriteFileEx(hComm, &pMyOl->buffer, sizeof(BYTE), pMyOl, &write_compl )) {
if (GetLastError() != ERROR_IO_PENDING) {
// WriteFile failed, but isn't delayed. Report error and abort.
free(pMyOl);
printf("last error: %ld",GetLastError());
return 0; //failed, return false;
}
else {
return -1; //pending
}
}
else {
free(pMyOl);
return 1; //finished
}
}
result = write_port(outPortHandle, 128);
result = write_port(outPortHandle, 131);
The lpBuf argument have to be pointers to buffers, not constants.
e.g.
char buffer;
buffer = 128;
result = write_port(outPortHandle, &buffer);
buffer = 131;
result = write_port(outPortHandle, &buffer);
What you really want to do is also pass a buffer length.
e.g.
char buffer[] = { 128, 131 };
result = write_port(outPortHandle, &buffer, sizeof(buffer));
int write_port(HANDLE hComm,BYTE* lpBuf, size_t length) {
...
// Issue write.
if (!WriteFileEx(hComm, &lpBuf, length, &osWrite, &write_compl )) {
...

Resources