Compile winapi with cygwin - c

I have tried compiling a windows executable using the win32api, however I have encountered many road blocks.
First thing to try was gcc -mno-cygwin [...] which results in gcc: error: unrecognized command line option '-mno-cygwin' which is strange since man gcc|grep -e '-mno-cygwin' is successful and mingw is installed.
No matter what other header files I try to include I always end up with unsatisfied circular include dependencies (a.h requires b.h requires a.h). What set of header files are required to properly compile an executable based on the win32 api?
header files I have tried:
w32api/winnt.h
w32api/ddk/ntddk.h
w32api/Windows.h
w32api/ntdef.h
source code:
$ cat source.c
#include <w32api/winnt.h>
#include <w32api/ddk/ntddk.h>
int main(int argc, char **argv) {
PHANDLE hProcess;
CLIENT_ID processId;
processId.UniqueProcess = (HANDLE) 1000;
processId.UniqueThread = 0;
NtOpenProcess(&hProcess, PROCESS_VM_READ|PROCESS_VM_WRITE, 0, &processId);
return 0;
}
$ gcc -o a.exe -I/usr/include/w32api -I/usr/include/w32api/ddk source.c
In file included from memoryEdit.c:1:0:
/usr/include/w32api/winnt.h:291:11: error: unknown type name 'CONST'
typedef CONST WCHAR *LPCWCH,*PCWCH;
^
[...]
$ gcc --version
gcc (GCC) 5.4.0
$ uname -a
CYGWIN_NT-6.1 HOST_NAME 2.5.2(0.297/5/3) 2016-06-23 14:29 x86_64 Cygwin

gcc -mno-cygwin has been removed ages ago.
If you want to compile a windows program you need to use not the gcc compiler, that is cygwin to cygwin, but the cross compilers cygwin to windows.
There are 2 package variants depending on the arch:
mingw64-i686-gcc
mingw64-x86_64-gcc

I had no troubles just now with a compilation in Eclipse/gcc. Here's my testfile:
/*
============================================================================
Name : win32gcctest.c
Author : Clark Thomborson
Version : 1.0
Copyright : Copyleft
Description : Testing winapi synchronous file access within Cygwin
============================================================================
*/
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <fileapi.h>
void my_write(char* fname) {
HANDLE hFile;
char DataBuffer[] = "This is some test data to write to the file.";
DWORD dwBytesToWrite = (DWORD) strlen(DataBuffer);
DWORD dwBytesWritten = 0;
BOOL bErrorFlag = FALSE;
hFile = CreateFile(fname, // name of the write
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // default security
CREATE_ALWAYS, // overwrite any existing file
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
if (hFile == INVALID_HANDLE_VALUE) {
DWORD last_err = GetLastError();
printf("Error code %d: unable to open file \"%s\" for write.\n", last_err, fname);
exit( last_err );
}
printf("Writing %d bytes to %s.\n", dwBytesToWrite, fname);
bErrorFlag = WriteFile(hFile,
DataBuffer, // start of data to write
dwBytesToWrite, // number of bytes to write
&dwBytesWritten, // number of bytes that were written
NULL); // no overlapped structure
if (FALSE == bErrorFlag) {
DWORD last_err = GetLastError();
printf("Error code %d: unable to write to file \"%s\".\n", last_err, fname);
exit( GetLastError() );
exit( last_err );
} else {
if (dwBytesWritten != dwBytesToWrite) {
// This is an error because a synchronous write that results in
// success (WriteFile returns TRUE) should write all data as
// requested. This would not necessarily be the case for
// asynchronous writes.
printf("Error: dwBytesWritten != dwBytesToWrite\n" );
exit( EXIT_FAILURE );
} else {
printf("Wrote %d bytes to %s successfully.\n", dwBytesWritten, fname);
}
}
CloseHandle(hFile);
}
HANDLE my_open_for_read(char* fname) {
HANDLE hFile;
hFile = CreateFile(
fname,
GENERIC_READ,
FILE_SHARE_DELETE, // another process may delete this file while this handle is open
NULL, // no security attributes
OPEN_EXISTING, // returns error if file not found
FILE_ATTRIBUTE_NORMAL, // no special attributes, so can't do async IO
NULL // no attributes will be copied from another file
);
if (hFile == INVALID_HANDLE_VALUE) {
DWORD last_err = GetLastError();
printf("Error code %d: unable to open file \"%s\" for read.\n", last_err, fname);
exit( last_err );
}
return hFile;
}
ssize_t my_read(HANDLE hFile, void *buffer, size_t bytes_to_read) {
DWORD bytes_read;
if (ReadFile(hFile, buffer, bytes_to_read, &bytes_read, NULL)) {
return (ssize_t) bytes_read;
} else {
DWORD last_err = GetLastError();
printf("Error code %d: unable to read file.\n", last_err );
exit( last_err );
}
}
int main(void) {
char fname[32] = "test.txt";
my_write( fname );
printf("Reading %s.\n", fname);
char buff[1024];
HANDLE hFile = my_open_for_read( fname );
ssize_t nc = my_read( hFile, buff, 1023 ); // allow room for terminating byte
if( nc >= 0 ) {
buff[nc] = 0; // terminate string
printf("Read %d characters: %s", (int) nc, buff);
return EXIT_SUCCESS;
} else { // buggy my_read()
printf("Error %d", (int) nc );
return nc;
}
}

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);

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.

Wrong print out of binary file using _tprintf

I must read a binary file, but I have wrong output. I start from a txt file that contains:
1 100000 Romano Antonio 1250
2 150000 Fabrizi Aldo 2245
3 200000 Verdi Giacomo 11115
4 250000 Rossi Luigi 13630
I generate the relative binary file by with program:
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#define BUF_SIZE 1000
/*
* Problem1: use tchar.h and _tmain instead of
* int main (int argc, LPTSTR argv [])
* Sometimes it is needeed to see argv correctly
*/
int _tmain (int argc, LPTSTR argv [])
{
HANDLE hIn, hOut;
DWORD nIn, nOut;
CHAR buffer [BUF_SIZE];
if (argc != 3) {
fprintf (stderr, "Usage: cp file1 file2\n");
return 1;
}
hIn = CreateFile (argv[1], GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); /*Here hIn is created with read access*/
if (hIn == INVALID_HANDLE_VALUE) {
fprintf (stderr,
"Cannot open input file. Error: %x\n", GetLastError ());
return 2;
}
hOut = CreateFile (argv[2], GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hOut == INVALID_HANDLE_VALUE) {
fprintf (stderr,
"Cannot open output file. Error: %x\n", GetLastError ());
CloseHandle(hIn);
return 3;
}
while (ReadFile (hIn, buffer, BUF_SIZE, &nIn, NULL) && nIn > 0) {
/*hIn is the handle to the read file, buffer is a pointer to the buffer that receives the data read
from the file, BUF_SIZE is the maximum number of bytes to be read, &nIn is
the pointer to the variable that receives the n° of bytes read*/
/*
* Problem 2:
* During the last cycle less than BUF_SIZE characters may
* be read from file
* WriteFile (hOut, buffer, BUF_SIZE, &nOut, NULL);
* so write just the number of characters read
*/
WriteFile (hOut, buffer, nIn, &nOut, NULL); /*I write in file related hOut, the content of read file hIn is in buffer,
nIn is the n° of bytes to write, &nOut is a pointer to the variable that receives the number of bytes written*/
if (nIn != nOut) {
fprintf (stderr, "Fatal write error: %x\n", GetLastError ());
CloseHandle(hIn); CloseHandle(hOut);
return 4;
}
}
CloseHandle (hIn);
CloseHandle (hOut);
return 0;
}
Now I think that it gives me a binary file. Then, I have to read this binary file and put the data into a struct. My code is:
#if 1
#define UNICODE
#define _UNICODE
#endif
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#define L 30+1
#define SETFILEPOINTER_OVERLAPPING 1
#define N 3
#define BUF_SIZE 1000
struct myacc {
int id;
long int acc_number;
TCHAR surname[L];
TCHAR name[L];
int amount;
};
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hIn;
OVERLAPPED ov = {0, 0, 0, 0, NULL};
DWORD nIn,n;
//TCHAR c;
//TCHAR buffer[BUF_SIZE];
LARGE_INTEGER filePos;
struct myacc account;
if(argc != N) {
fprintf(stderr, "Error into arguments\n");
return 1;
}
hIn = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hIn == INVALID_HANDLE_VALUE) {
fprintf (stderr,"Cannot open input file. Error: %x\n", GetLastError ());
return 2;
}
n=1;
filePos.QuadPart = (n-1) * sizeof(struct myacc);
#if SETFILEPOINTER_OVERLAPPING
SetFilePointerEx (hIn, filePos, NULL, FILE_BEGIN);
while(ReadFile (hIn, &account, sizeof (struct myacc), &nIn, NULL) && nIn > 0) {
_tprintf (_T("-> %d %ld %s %s %d <-\n"), account.id, account.acc_number, account.surname, account.name, account.amount);
}
#else
ov.Offset = filePos.LowPart; /*Uso l'overlapped structure ov se ho asynchronous I/O*/
ov.OffsetHigh = filePos.HighPart;
while(ReadFile (hIn, &account, sizeof (struct myacc), &nIn, &ov) && nIn > 0) {
_tprintf (_T("-> %d %ld %s %s %d <-\n"), account.id, account.acc_number, account.surname, account.name, account.amount);
}
#endif
return 0;
}
Now, in this part of code
while(ReadFile (hIn, &account, sizeof (struct myacc), &nIn, NULL) && nIn > 0) {
_tprintf (_T("-> %d %ld %s %s %d <-\n"), account.id, account.acc_number, account.surname, account.name, account.amount);
}
the output is wrong, that is:
Why do I get this? I generate wrong bin file? Or I manage bad the output function? I hope you can help me.
Thank you in advance.
You believe that second program is wrong, but we don't know if it is wrong because the input for the second program is also wrong.
Input for the second program (also output of the first program) is supposed to be a binary file, but it is actually a text file, identical to the the input of the first program. It is identical because the first program is not making any kind of conversion. All it does is ReadFile(..., buffer, ..., &nIn, ...) immediately followed by WriteFile(..., buffer, nIn, ...). These two lines just copy all the data.
First program should use getline() (like described here, in a second method, line-based parsing) instead of ReadFile(), get all the data, populate one struct myacc object, and WriteFile contents of that object.

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;
}

How to get the list of all drives in C

Is there any method using which i can list down all the available drives and their folder content. ie i want to access all the drives and then the folders in each drive and then the sub-folders of each folder and so on till the last possible level in each drive.
C language .. Windows platform .. i have tried using alphabetic array with system() but am unable to get the names of files and folders .
This is not "standard C" (ie: ANSI, C89, C99, etc), but it makes minimal use of operating-system specific calls (ie: just "windows.h", not MS .NET or MFC technologies). This is the minimalist approach to what you are attempting to do. Once you have a list of all drive letters, you need to query each drive recursively for its directory listings.
This is a mix of C and C++, but you'll likely be using a free version of Visual Studio to build this anyways.
Code Listing - Get drive letters
#include <windows.h>
#include <stdio.h>
int main()
{
char buf[255];
// get the drive letters as a set of strings
int sz = GetLogicalDriveStrings(sizeof(buf), buf);
if( sz > 0)
{
// buf now contains a list of all the drive letters. Each drive letter is
// terminated with '\0' and the last one is terminated by two consecutive '\0' bytes.
char* p1 = buf;
char* p2;
while( *p1 != '\0' && (p2 = strchr(p1,'\0')) != NULL )
{
printf("%s\n", p1);
p1 = p2+1;
}
}
else
{
// Oops! something went wrong so display the error message
DWORD dwError = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, dwError, 0, buf, sizeof(buf), 0);
printf("%s\n", buf);
}
}
Code Listing - Directory listing
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#pragma comment(lib, "User32.lib")
void DisplayErrorBox(LPTSTR lpszFunction);
int _tmain(int argc, TCHAR *argv[])
{
WIN32_FIND_DATA ffd;
LARGE_INTEGER filesize;
TCHAR szDir[MAX_PATH];
size_t length_of_arg;
HANDLE hFind = INVALID_HANDLE_VALUE;
DWORD dwError=0;
// If the directory is not specified as a command-line argument,
// print usage.
if(argc != 2)
{
_tprintf(TEXT("\nUsage: %s <directory name>\n"), argv[0]);
return (-1);
}
// Check that the input path plus 3 is not longer than MAX_PATH.
// Three characters are for the "\*" plus NULL appended below.
StringCchLength(argv[1], MAX_PATH, &length_of_arg);
if (length_of_arg > (MAX_PATH - 3))
{
_tprintf(TEXT("\nDirectory path is too long.\n"));
return (-1);
}
_tprintf(TEXT("\nTarget directory is %s\n\n"), argv[1]);
// Prepare string for use with FindFile functions. First, copy the
// string to a buffer, then append '\*' to the directory name.
StringCchCopy(szDir, MAX_PATH, argv[1]);
StringCchCat(szDir, MAX_PATH, TEXT("\\*"));
// Find the first file in the directory.
hFind = FindFirstFile(szDir, &ffd);
if (INVALID_HANDLE_VALUE == hFind)
{
DisplayErrorBox(TEXT("FindFirstFile"));
return dwError;
}
// List all the files in the directory with some info about them.
do
{
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
_tprintf(TEXT(" %s <DIR>\n"), ffd.cFileName);
}
else
{
filesize.LowPart = ffd.nFileSizeLow;
filesize.HighPart = ffd.nFileSizeHigh;
_tprintf(TEXT(" %s %ld bytes\n"), ffd.cFileName, filesize.QuadPart);
}
}
while (FindNextFile(hFind, &ffd) != 0);
dwError = GetLastError();
if (dwError != ERROR_NO_MORE_FILES)
{
DisplayErrorBox(TEXT("FindFirstFile"));
}
FindClose(hFind);
return dwError;
}
void DisplayErrorBox(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message and clean up
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
References
List Windows Logical Drive Letters, Accessed 2014-08-01, <http://www.daniweb.com/software-development/c/code/237803/list-windows-logical-drive-letters>
Listing the Files in a Directory, Accessed 2014-08-01, <http://msdn.microsoft.com/en-us/library/windows/desktop/aa365200%28v=vs.85%29.aspx>
Standard C has no way to directly address the drive, or, for that matter, even know what a drive is.
Generally, each C compiler vendor will include a library which handles those things for the specific platform the compiler is written for. But these are all specific to the vendor.
Boost has cross-platform library for C++, including one for dealing with the file system.

Resources