Named shared memory Windows api c++ - c

I am trying to share some data between 2 processes. The first writes the data in mapped file and the second reads it.
Here's my code so far:
First process:
#include "stdafx.h"
#include <Windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include<stdio.h>
#define BUF_SIZE 256
int _tmain(int argc, _TCHAR* argv[]) {
TCHAR szName[] = TEXT("Global\\MyFileMappingObject");
LPTSTR szMsg = TEXT("MESS");
HANDLE tokenH;
TOKEN_PRIVILEGES tp;
LUID luid;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenH)) {
printf("OpenProcessToken error: %u\n", GetLastError());
return FALSE;
}
if (!LookupPrivilegeValue(NULL, SE_CREATE_GLOBAL_NAME, &luid)) {
printf("LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(tokenH, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) {
printf("AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
CloseHandle(tokenH);
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
BUF_SIZE,
szName);
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = (LPTSTR)MapViewOfFile(hMapFile,
FILE_MAP_ALL_ACCESS,
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
UnmapViewOfFile(pBuf);
printf("Done\n");
CloseHandle(hMapFile);
return 0;
}
Second process:
#include "stdafx.h"
#include <Windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <stdio.h>
#pragma comment(lib, "user32.lib")
#define BUF_SIZE 256
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR szName[] = TEXT("Global\\MyFileMappingObject");
HANDLE tokenH;
TOKEN_PRIVILEGES tp;
LUID luid;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenH);
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
printf("LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(tokenH, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) {
printf("AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
CloseHandle(tokenH);
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = OpenFileMapping(
FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not open file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = (LPTSTR)MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return 0;
}
The first process manages to write its data (I don't receive any error message and get the "Done" message), but the problem is with the the second process.
After "OpenFileMapping", I get from getLastError the code 2 which is for non-existent file. I run both processes as administrator.

Error 2 is ERROR_FILE_NOT_FOUND, which means the named mapping object does not exist at the time OpenFileMapping() is called.
In order to share a named kernel object between processes, both processes need to be running at the same time. Like other named kernel objects (events, mutexes, etc), a mapping object has a reference count associated with it, where each open handle increments the reference count. After all handles are closed, the object is destroyed.
So, when the first app unmaps its view and closes its handle to the mapping object, the object will be destroyed if the second app does not already have its own handle open to the same mapping object. Thus the object will not exist when the second app tries to open it.

Related

How to read data from COM port with C language

I have been coding on C/C++ for a while but now I have faced a major problem which I can not resolve. I am trying to communicate with COM port. First I am sending data with WriteFile(), this part works.But when it comes to receiving an answer from the port with ReadFile(), I do not get anything.
Here is the code:
#include <stdlib.h>
#include <windows.h>
#include <stdio.h>
#include <conio.h>
int main(int argc, char *argv[])
{
int n=0;
DCB dcb={0};
HANDLE hCom;
BOOL fSuccess;
char *pcCommPort = "COM3";
DWORD dwBytesRead=0;
DWORD dwRead;
DWORD dwBytesWrite=0;
DWORD dwWrite=0;
/***************************************CommTimeouts******************************************/
COMMTIMEOUTS timeouts={0};
timeouts.ReadIntervalTimeout=200;
//timeouts.ReadTotalTimeoutConstant=1;
//timeouts.ReadTotalTimeoutMultiplier=1;
timeouts.WriteTotalTimeoutConstant=2;
//timeouts.WriteTotalTimeoutMultiplier=1;
/*******************************************Handle*******************************************/
hCom = CreateFile( pcCommPort,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, // must be opened with exclusive-access
NULL, // no security attributes
OPEN_EXISTING, // must use OPEN_EXISTING
FILE_ATTRIBUTE_NORMAL, // not overlapped I/O
NULL // hTemplate must be NULL for comm devices
);
/***************************************SET*UP*COM*PORT**************************************/
if (hCom == INVALID_HANDLE_VALUE)
{
printf ("CreateFile failed with error %d.\n", GetLastError());
CloseHandle(hCom);
return (1);
}
if(!SetCommTimeouts(hCom, &timeouts))
{
/*Well, then an error occurred*/
}
fSuccess = GetCommState(hCom, &dcb);
if (!fSuccess)
{
/*More Error Handling*/
printf ("GetCommState failed with error %d.\n", GetLastError());
CloseHandle(hCom);
return (2);
}
dcb.BaudRate = 9600; // set the baud rate
dcb.ByteSize = 8; // data size, xmit, and rcv
dcb.Parity = EVENPARITY; // no parity bit
dcb.StopBits = ONESTOPBIT; // one stop bit
fSuccess = SetCommState(hCom, &dcb);
if (!fSuccess)
{
printf ("SetCommState failed. Error: %d.\n", GetLastError());
CloseHandle(hCom);
return (3);
}
printf ("Serial port %s successfully configured.\n", pcCommPort);
// return (0);
/*************************************Writing************************************************/
char bytes_to_send[] = {'36'};
if(!WriteFile(hCom, bytes_to_send, 2, &dwBytesWrite, NULL))
{
fprintf(stderr, "Error\n");
CloseHandle(hCom);
return 1;
}
printf("dwBytesWrite = %d | %x\n", dwBytesWrite, (dwBytesWrite));
/*************************************Reading************************************************/
char bytes_to_receive[7];
if(!ReadFile(hCom, bytes_to_receive, 7, &dwBytesRead, NULL)){
printf ("SetCommState failed. Error: %d.\n", GetLastError());
CloseHandle(hCom);
return (4);
} else {
printf("Bytes read %d -> %d\n",dwBytesRead, bytes_to_receive);}
/********************************************************************************************/
CloseHandle(hCom);
return(0);
}
There is a file pointer, both for read and write. After the WriteFile it is at the end of the file. If you try to read from it, you will read at the end of the file. To read what you just wrote you have to reposition the file pointer at the start of the file, using the SetFilePointer function:
SetFilePointer(hCom, 0, NULL, FILE_BEGIN);

Enable large pages in Windows programmatically

I want to use large pages in my app like this:
VirtualAlloc(NULL, n_bytes, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE, PAGE_READWRITE);
I plan to enable large pages for the current user during installation, while having elevated admin rights. Does anyone have code for enabling large pages programmatically?
I'm posting what I've gathered.
The general idea:
Enable large pages for the current user account. (Requires admin rights).
Enable large pages for the current process token. (Requires admin rights).
Allocate the memory (granular to large page size, 2Mb, in fact).
If you have UAC properly disabled, you need to execute step 1 only once with admin rights. If you have UAC enabled, you always have to execute it all with admin rights.
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <ntsecapi.h>
#include <ntstatus.h>
#include <Sddl.h>
void InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String)
{
DWORD StringLength;
if (String == NULL) {
LsaString->Buffer = NULL;
LsaString->Length = 0;
LsaString->MaximumLength = 0;
return;
}
StringLength = wcslen(String);
LsaString->Buffer = String;
LsaString->Length = (USHORT)StringLength * sizeof(WCHAR);
LsaString->MaximumLength = (USHORT)(StringLength + 1) * sizeof(WCHAR);
}
NTSTATUS OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle)
{
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
LSA_UNICODE_STRING ServerString;
PLSA_UNICODE_STRING Server = NULL;
//
// Always initialize the object attributes to all zeroes.
//
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
if (ServerName != NULL) {
//
// Make a LSA_UNICODE_STRING out of the LPWSTR passed in
//
InitLsaString(&ServerString, ServerName);
Server = &ServerString;
}
//
// Attempt to open the policy.
//
return LsaOpenPolicy(
Server,
&ObjectAttributes,
DesiredAccess,
PolicyHandle
);
}
NTSTATUS SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid, LPWSTR PrivilegeName, BOOL bEnable)
{
LSA_UNICODE_STRING PrivilegeString;
//
// Create a LSA_UNICODE_STRING for the privilege name.
//
InitLsaString(&PrivilegeString, PrivilegeName);
//
// grant or revoke the privilege, accordingly
//
if (bEnable) {
return LsaAddAccountRights(
PolicyHandle, // open policy handle
AccountSid, // target SID
&PrivilegeString, // privileges
1 // privilege count
);
}
else {
return LsaRemoveAccountRights(
PolicyHandle, // open policy handle
AccountSid, // target SID
FALSE, // do not disable all rights
&PrivilegeString, // privileges
1 // privilege count
);
}
}
void main()
{
HANDLE hToken = NULL;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
applog(LOG_INFO, "OpenProcessToken failed. GetLastError returned: %d\n", GetLastError());
return -1;
}
DWORD dwBufferSize = 0;
// Probe the buffer size reqired for PTOKEN_USER structure
if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwBufferSize) &&
(GetLastError() != ERROR_INSUFFICIENT_BUFFER))
{
applog(LOG_INFO, "GetTokenInformation failed. GetLastError returned: %d\n", GetLastError());
// Cleanup
CloseHandle(hToken);
hToken = NULL;
return -1;
}
PTOKEN_USER pTokenUser = (PTOKEN_USER) malloc(dwBufferSize);
// Retrieve the token information in a TOKEN_USER structure
if (!GetTokenInformation(
hToken,
TokenUser,
pTokenUser,
dwBufferSize,
&dwBufferSize))
{
applog(LOG_INFO, "GetTokenInformation failed. GetLastError returned: %d\n", GetLastError());
// Cleanup
CloseHandle(hToken);
hToken = NULL;
return -1;
}
// Print SID string
LPWSTR strsid;
ConvertSidToStringSid(pTokenUser->User.Sid, &strsid);
applog(LOG_INFO, "User SID: %S\n", strsid);
// Cleanup
CloseHandle(hToken);
hToken = NULL;
NTSTATUS status;
LSA_HANDLE policyHandle;
if (status = OpenPolicy(NULL, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &policyHandle))
{
applog(LOG_INFO, "OpenPolicy %d", status);
}
// Add new privelege to the account
if (status = SetPrivilegeOnAccount(policyHandle, pTokenUser->User.Sid, SE_LOCK_MEMORY_NAME, TRUE))
{
applog(LOG_INFO, "OpenPSetPrivilegeOnAccountolicy %d", status);
}
// Enable this priveledge for the current process
hToken = NULL;
TOKEN_PRIVILEGES tp;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
{
applog(LOG_INFO, "OpenProcessToken #2 failed. GetLastError returned: %d\n", GetLastError());
return -1;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &tp.Privileges[0].Luid))
{
applog(LOG_INFO, "LookupPrivilegeValue failed. GetLastError returned: %d\n", GetLastError());
return -1;
}
BOOL result = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
DWORD error = GetLastError();
if (!result || (error != ERROR_SUCCESS))
{
applog(LOG_INFO, "AdjustTokenPrivileges failed. GetLastError returned: %d\n", error);
return -1;
}
// Cleanup
CloseHandle(hToken);
hToken = NULL;
SIZE_T pageSize = GetLargePageMinimum();
// Finally allocate the memory
char *largeBuffer = VirtualAlloc(NULL, pageSize * N_PAGES_TO_ALLOC, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
if (largeBuffer)
{
applog(LOG_INFO, "VirtualAlloc failed, error 0x%x", GetLastError());
}
}

Passing a HANDLE to a DLL

I'm new to Win32 programming.
I'm trying to pass a HANDLE obtained using CreateFile() to a function in a DLL.
But upon trying to read bytes, dwBytesRead says 0.
Am I allowed to pass HANDLEs to DLL entries? I read here [Writing DLLs] that resources of the caller do not belong to callee, and hence I should not call CloseHandle() or things like free() for malloc() in caller.
Is my understanding correct? Kindly point me in the right direction. Here's the code:
main.c
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#define BUFFERSIZE 5
int __declspec( dllimport ) hello( HANDLE );
void __cdecl _tmain(int argc, TCHAR *argv[])
{
HANDLE hFile;
printf("\n");
if( argc != 2 )
{
printf("Usage Error: Incorrect number of arguments\n\n");
_tprintf(TEXT("Usage:\n\t%s <text_file_name>\n"), argv[0]);
return;
}
hFile = CreateFile(argv[1], // file to open
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // normal file
NULL); // no attr. template
if (hFile == INVALID_HANDLE_VALUE)
{
_tprintf(TEXT("Terminal failure: unable to open file \"%s\" for read.\n"), argv[1]);
return;
}
printf( "Entered main, calling DLL.\n" );
hello(hFile);
printf( "Back in main, exiting.\n" );
CloseHandle(hFile);
}
hello.c
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#define BUFFERSIZE 5
DWORD g_BytesTransferred = 0;
VOID CALLBACK FileIOCompletionRoutine(
__in DWORD dwErrorCode,
__in DWORD dwNumberOfBytesTransfered,
__in LPOVERLAPPED lpOverlapped )
{
_tprintf(TEXT("Error code:\t%x\n"), dwErrorCode);
_tprintf(TEXT("Number of bytes:\t%x\n"), dwNumberOfBytesTransfered);
g_BytesTransferred = dwNumberOfBytesTransfered;
}
int __declspec( dllexport ) hello( HANDLE hFile )
{
DWORD dwBytesRead = 0;
char ReadBuffer[BUFFERSIZE] = {0};
OVERLAPPED ol = {0};
if( FALSE == ReadFileEx(hFile, ReadBuffer, BUFFERSIZE-1, &ol, FileIOCompletionRoutine) )
{
DWORD lastError = GetLastError();
printf("Terminal failure: Unable to read from file.\n GetLastError=%08x\n", lastError);
return lastError;
}
dwBytesRead = g_BytesTransferred;
if (dwBytesRead > 0 && dwBytesRead <= BUFFERSIZE-1)
{
ReadBuffer[dwBytesRead]='\0';
printf("Data read from file (%d bytes): \n", dwBytesRead);
printf("%s\n", ReadBuffer);
}
else if (dwBytesRead == 0)
{
printf("No data read from file \n");
}
else
{
printf("\n ** Unexpected value for dwBytesRead ** \n");
}
printf( "Hello from a DLL!\n" );
return( 0 );
}
You are missing the SleepEx(5000, TRUE) call from the example.
You are using async-io, in which case you will receive a callback when the read occurs. If you don't wait for the callback you may get 0 bytes read depending on when the callback is triggered.

How to Send IOCTL's to all drivers on windows in C

Can someone provide me with a sample C code that list´s all device Names that i can open with Createfile()? i always get error code 3 : path does not exist
sample code that doesnt works:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#include <regstr.h>
#include <devioctl.h>
#include <usb.h>
#include <usbiodef.h>
#include <usbioctl.h>
#include <usbprint.h>
#include <setupapi.h>
#include <devguid.h>
#include <wdmguid.h>
#pragma comment(lib, "Setupapi.lib")
int main(void){
HDEVINFO deviceInfoList;
deviceInfoList = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
if (deviceInfoList != INVALID_HANDLE_VALUE)
{
SP_DEVINFO_DATA deviceInfoData;
deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (DWORD i = 0; SetupDiEnumDeviceInfo(deviceInfoList, i, &deviceInfoData); i++)
{
LPTSTR buffer = NULL;
DWORD buffersize = 0;
while (!SetupDiGetDeviceInstanceIdA(deviceInfoList, &deviceInfoData, buffer, buffersize, &buffersize))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
if (buffer) delete buffer;
buffer = new TCHAR[buffersize];
}
else
{
printf("%ls\n", "error");
break;
}
}
HANDLE hFile = CreateFileA(buffer,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hFile == INVALID_HANDLE_VALUE) {
printf("InvalidHandle, error code: %d\n", GetLastError());
}
CloseHandle(hFile);
printf("%s\n", buffer);
if (buffer) { delete buffer; buffer = NULL; }
}
}
getchar();
}
my Goal is to print all valid device Names and try to get a valid handle on it that i can later user for sending ioctl`s
thx
EDIT:
ok abhineet so thats what i got now :
DWORD EnumerateDevices(){
DWORD dwResult = 0;
HDEVINFO hdev = SetupDiGetClassDevs(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);// DIGCF_ALLCLASSES
/*HDEVINFO hdev =SetupDiGetClassDevs(NULL,
0, // Enumerator
0,
DIGCF_PRESENT | DIGCF_ALLCLASSES); */
if (INVALID_HANDLE_VALUE != hdev) {
for (int idev = 0; idev < 100; idev++)
{
SP_DEVICE_INTERFACE_DATA did = { 0 };
did.cbSize = sizeof(did);
if (SetupDiEnumDeviceInterfaces(hdev, NULL, &GUID_DEVCLASS_BATTERY, idev, &did))
{
DWORD cbRequired = 0;
SetupDiGetDeviceInterfaceDetail(hdev,
&did,
NULL,
0,
&cbRequired,
0);
if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
{
PSP_DEVICE_INTERFACE_DETAIL_DATA pdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, cbRequired);
if (pdidd) {
pdidd->cbSize = sizeof(*pdidd);
if (SetupDiGetDeviceInterfaceDetail(hdev, &did, pdidd, cbRequired, &cbRequired, 0)) {
wprintf(L"%s\n", pdidd->DevicePath);
HANDLE hBattery = CreateFile(pdidd->DevicePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE != hBattery)
{
printf("Successfully opened Handle\n");
CloseHandle(hBattery);
}
else{
wprintf(L"CreateFile(%s) failed %d\n", pdidd->DevicePath, GetLastError());
}
}
else{
printf("SetupDiGetDeviceInterfaceDetail() failed %d\n", GetLastError());
}
LocalFree(pdidd);
}
}
else{
printf("SetupDiGetDeviceInterfaceDetail() failed %d\n", GetLastError());
}
}
else if (ERROR_NO_MORE_ITEMS == GetLastError())
{
printf("-NoMoreItems-");
break; // Enumeration failed - perhaps we're out of items
}
}
SetupDiDestroyDeviceInfoList(hdev);
}
else{
printf("SetupDiGetClassDevs() failed %d\n", GetLastError());
}
return dwResult;
}
i ripped the most from here : https://msdn.microsoft.com/en-us/library/windows/desktop/bb204769(v=vs.85).aspx
and my Output is :
\\?\acpi#pnp0c0a#1#{72631e54-78a4-11d0-bcf7-00aa00b7b32a}
Successfully opened Handle
-NoMoreItems-
at least i got a valid handle!
so i wanna do this an all devices avaible on the System , how to do that?
IMHO, I don't think, you can do a CreateFile on InstanceID. To do a CreateFile, you need the symbolic name of the device. You can use the following SetupAPIs,
SetupDiEnumDeviceInterfaces
SetupDiGetDeviceInterfaceDetail
The Remark section of both APIs state that,
SetupDiEnumDeviceInterfaces:: DeviceInterfaceData points to a structure that identifies a requested
device interface. To get detailed information about an interface, call
SetupDiGetDeviceInterfaceDetail. The detailed information includes the
name of the device interface that can be passed to a Win32 function
such as CreateFile (described in Microsoft Windows SDK documentation)
to get a handle to the interface.
SetupDiGetDeviceInterfaceDetail:: The interface detail returned by this function consists of a device path that can be passed to Win32
functions such as CreateFile. Do not attempt to parse the device path
symbolic name. The device path can be reused across system starts.
This might be of your use, how to get DevicePath from DeviceID

WIndow CreateFile ReadFile WriteFile

I am a student so I apologize up front for not using the correct forum protocols. I am new to C, and really new to Win32 API. My assignment is to write a small C program that copies the contents of an existing file to a new file, using only Win32 I/O system calls: CreateFile(), ReadFile(), WriteFile(), etc... File names are to be specified on the command line. Right now I'm just trying to get the basics functions in place, I will then focus on error handling. This code compiles, creates a new file, but the data does not get copied to it. Any advice? thanks for taking a look!
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main(int argc, char *argv[])
{
char buff[4096];
DWORD dwBytesRead, dwBytesWritten;
DWORD dwBytesToWrite = (DWORD)strlen(buff);
//open source file and read it
HANDLE source;
// Create a handle for the source file
source=CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
// Check for errors
if ( source == INVALID_HANDLE_VALUE ){
printf("Error, source file not opened.");
exit(EXIT_FAILURE);
}
else printf("The source file is %s\n", argv[1]);
//create a new file
HANDLE target;
target = CreateFile(argv[2], GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if ( target == INVALID_HANDLE_VALUE ){
printf("Error, target file not created.");
exit(EXIT_FAILURE);
}
else printf("The source file is %s\n", argv[2]);
//copy contents
ReadFile(source, buff, 4096, &dwBytesRead, NULL);
WriteFile(target, buff, dwBytesToWrite, &dwBytesWritten, NULL);
//copy complete
CloseHandle(source);
CloseHandle(target);
return 0;
}
As mentioned in comments, your code has a few mistakes in it. Try something more like this instead:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main(int argc, char *argv[])
{
char buff[4096];
DWORD dwBytesRead, dwBytesWritten;
// Open the source file
HANDLE source = CreateFileA(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
// Check for error
if (source == INVALID_HANDLE_VALUE) {
printf("Source file not opened. Error %u", GetLastError());
return EXIT_FAILURE;
}
printf("The source file is %s\n", argv[1]);
// Create a new file
HANDLE target = CreateFileA(argv[2], GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// Check for error
if (target == INVALID_HANDLE_VALUE) {
printf("Target file not created. Error %u", GetLastError());
CloseHandle(source);
return EXIT_FAILURE;
}
printf("The target file is %s\n", argv[2]);
// Copy contents
bool ok = true;
do {
// Read file, check for error
if (!ReadFile(source, buff, sizeof(buff), &dwBytesRead, NULL)) {
printf("Source file not read from. Error %u", GetLastError());
ok = false;
break;
}
// Check for EOF reached
if (dwBytesRead == 0) {
break;
}
// Write file, check for error
if (!WriteFile(target, buff, dwBytesRead, &dwBytesWritten, NULL)) {
printf("Target file not written to. Error %u", GetLastError());
ok = false;
break;
}
}
while (true);
// Copy complete
CloseHandle(source);
CloseHandle(target);
// Check for error
if (!ok) {
DeleteFileA(argv[2]);
return EXIT_FAILURE;
}
// all OK
return 0;
}

Resources