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
Related
I am trying to write a DLL injector to perform a DLL injector on a calculator process.
I wrote the DLL injector program in C and the DLL but the injector dosent inject the DLL or any other DLL (I tried to take some random windows DLL that the calculator doesn't use).
#include <stdio.h>
#include <Windows.h>
int main() {
LPCSTR dllpath = "C:\\Users\\......\\Dll1.dll";
printf("#### Starting ####\n");
printf("step 1: attaching the target process memory\n");
HANDLE hProcess = OpenProcess(
PROCESS_ALL_ACCESS,
FALSE,
6456 // target process id
);
if (hProcess != NULL) {
printf("step 2: allocate the target memory process\n");
LPVOID dllPathMemoryAddr = VirtualAllocEx(
hProcess,
NULL,
strlen(dllpath),
MEM_RESERVE | MEM_COMMIT,
PAGE_EXECUTE_READWRITE
);
if (dllPathMemoryAddr != NULL) {
printf("step 3: write to the process memory\n");
BOOL succeededWriting = WriteProcessMemory(
hProcess,
dllPathMemoryAddr,
dllpath,
strlen(dllpath),
NULL
);
if (succeededWriting) {
printf("step 4: execute.\n");
FARPROC loadLibAddr = GetProcAddress(
GetModuleHandle(TEXT("kernel32.dll")),
"LoadLibraryA"
);
HANDLE rThread = CreateRemoteThread(
hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)loadLibAddr,
dllPathMemoryAddr,
0,
NULL
);
}
}
CloseHandle(hProcess);
}
return TRUE;
}
after running the injector I get this output:
#### Starting ####
step 1: attaching the target process memory
step 2: allocate the target memory process
step 3: write to the process memory
step 4: execute.
after that, I am still unable to see in process explorer the new DLL.
You are calling GetProcAddress() to get the address of LoadLibraryA(), this is returning the address of LoadLibraryA in your local process not the injected one. This is not guaranteed to be correct in the external process. You do not need to get the address manually, CreateRemoteThread will resolve the address for you.
Here is a very simple injector example that will explain how to do it
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
DWORD GetPid(char * targetProcess)
{
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snap && snap != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
if (Process32First(snap, &pe))
{
do
{
if (!_stricmp(pe.szExeFile, targetProcess))
{
CloseHandle(snap);
return pe.th32ProcessID;
}
} while (Process32Next(snap, &pe));
}
}
return 0;
}
int main()
{
char * dllpath = "C:\\Users\\me\\Desktop\\dll.dll";
char * processToInject = "csgo.exe";
long pid = 0;
while (!pid)
{
pid = GetPid(processToInject);
Sleep(10);
}
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
if (hProc && hProc != INVALID_HANDLE_VALUE)
{
void * loc = VirtualAllocEx(hProc, 0, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
WriteProcessMemory(hProc, loc, dllpath, strlen(dllpath) + 1, 0);
HANDLE hThread = CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, loc, 0, 0);
CloseHandle(hThread);
}
CloseHandle(hProc);
return 0;
}
I found the problem. I compiled the DLL as 64 but accidentally compiled the DLL injector has complied as 32 bit.
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);
Here's a link to the docs for the function:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa446654(v=vs.85).aspx
I've written code that /should/ work, but instead when called, errors out with ERROR_INVALID_SECURITY_DESCR. My code is supposed to copy a known working guid from one folder to another, but I'll take any working example code that doesn't error out on SetSecurityDescriptorGroup when modifying a SecurityDescriptor for a file or folder.
As you can see below, my code checks the validity of everything, including the security descriptors, yet the error '1338' still happens on the call to SetSecurityDescriptorGroup.
'1338' is "ERROR_INVALID_SECURITY_DESCR".
#include "stdafx.h"
#include <windows.h>
#include <AclAPI.h>
#include <sddl.h>
#include <iostream>
using std::wcout;
#include <string>
using std::string;
using std::wstring;
int main()
{
PSECURITY_DESCRIPTOR pGoodSecurityDescriptor = NULL;
LPCWSTR goodFilename = L"\\\\?\\UNC\\server\\home\\good";
if (! (ERROR_SUCCESS == GetNamedSecurityInfo(goodFilename, SE_FILE_OBJECT,
SACL_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION,
NULL, NULL, NULL, NULL, &pGoodSecurityDescriptor)))
{
_tprintf(_T("GetNamedSecurityInfo Error %u\n"), GetLastError());
return -1;
}
if (!IsValidSecurityDescriptor(pGoodSecurityDescriptor))
{
_tprintf(_T("IsValidSecurityDescriptor Error %u\n"), GetLastError());
return -1;
}
PSECURITY_DESCRIPTOR pBadSecurityDescriptor = NULL;
LPCWSTR badFilename = L"\\\\?\\UNC\\server\\home\\bad";
if (!(ERROR_SUCCESS == GetNamedSecurityInfo(badFilename, SE_FILE_OBJECT,
SACL_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION,
NULL, NULL, NULL, NULL, &pBadSecurityDescriptor)))
{
_tprintf(_T("GetNamedSecurityInfo Error %u\n"), GetLastError());
return -1;
}
if (!IsValidSecurityDescriptor(pBadSecurityDescriptor))
{
_tprintf(_T("IsValidSecurityDescriptor Error %u\n"), GetLastError());
return -1;
}
PSID pGroup = (PSID)LocalAlloc(LPTR, sizeof(PSID));
BOOL groupDefaulted = FALSE;
if (!GetSecurityDescriptorGroup(pGoodSecurityDescriptor, &pGroup, &groupDefaulted))
{
_tprintf(_T("GetSecurityDescriptorGroup Error %u\n"), GetLastError());
return -1;
}
if (!IsValidSid(pGroup))
{
_tprintf(_T("IsValidSid Error %u\n"), GetLastError());
return -1;
}
SetLastError(0);
if (!SetSecurityDescriptorGroup(pBadSecurityDescriptor, &pGroup, groupDefaulted))
{
_tprintf(_T("SetSecurityDescriptorGroup Error %u\n"), GetLastError());
return -1;
}
return 0;
}
The GetNamedSecurityInfo() function creates a security descriptor in self-relative format, but the SetSecurityDescriptorGroup() function requires a security descriptor in absolute format. You can convert from relative format to absolute format using MakeAbsoluteSD().
(See also Absolute and Self-Relative Security Descriptors in MSDN.)
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.
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;
}