Topic 20:
Example: Reporting Errors
We will discuss an example of reporting errors. Windows have provide certain
API’s in which the functions of getlasterror() and formatmessage(), we will see
how we can use these functions to report errors. For this we will make a generic
function that we will use in reporting errors.
To write code we need following customized header files
● Enviornment.h
● Everything.h
Enviornment.h includes macros for the environment of the program which is
basically used of UNICODE macro.
#if(WIN32_WINNT>=0x600)
#define WIN32_WINNT 0x600 /* Enable use of NT 5 (XP,2000,2003) functions
*/
#else
#if (WIN32_WINNT>=0x500 ) /*enable use of NT5(XP,2000,2003) functions */
#endif
#endif
In environment.h we have also
#ifdef UNICODE
#define_UNICODE
#endif
#ifndef UNICODE
#undef_UNICODE
#endif
#define LANG_DFLT LANG_ENGLISH // set default language
#define SUBLANG_DFLT SUBLANG_ENGLISH_US
Everything.h includes all the header file that will be typically required for all the
subsequent window programs.
#include “ENVIORNMENT.h
#include<windows.h> // all headers
#include<tchar.h> // generic functions
#include<stdio.h> // use for working in CLI
#include<stdlib.h>
#include<malloc.h>// memory allocation
#include<io.h> // input output operations
#include<WinSock2.h> // for windows socket operations
#include “support.h”
#include _MT
#include <process.h> // for multi tasking and multi threading
#endif
Following is the code of reporting errors.
#include “Everything.h”
VOID ReportError{LPCTSTR userMessage, DWORD exitCode, BOOL
printErrorMessage}
DWORD eMsgLen, errNum=GetLastError();
LPSTR lpvSysMsg;
_ftprint(stderr,_t(“%s\n”},userMessage};
If (printErrorMessage)
eMsgLen= FormatMessage{FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMATE_MESSAGE_FROM_SYSTEM,
NULL,errNUM,MAKELANGID{LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&lpsSysMSg,0,NULL);
If(eMsgLen>0)
_ftprint(stder,T(“%s\n”|,lpvSysMsg));
Else
_ftprint{stderr,_T{“LastErrorNumber,%d\n”},errNum};
If (lpvSysMsg!=NULL) LOCALFree(lpvSysMsg);
If(exitCode>0)
ExitProcess(exitCode);
return;
}
Topic 21:- Standard IO devices:
Reading Material:
There are three standard IO devices used in Operating system.
● Input
● Output
● Error
An input operation is performed by default on standard IO devices. For example we
does not mention in printf command where to print, it print the letter or any string by
default on standard Output device and in getch, character is get by default input device.
All the IO devices are manipulate in windows through handles.
Certain APIs are used to acquire handle to standard IO devices.
HANDLE GetStdHandle(DWORD nStdHandle);
● It returns a valid handle if the function succeed
● In case of failure it return INVALID_HANDEL_VALUE
● Successive calls to the functions will still run the same handle
● If the handle is closed it makes it subsequently unusable for the process in
future.
Three types of values can be pass to the nSTDHandle
1. STD_INPUT_HANDLE
2. STD_OUPUT_HANDLE
3. STD_ERROR_HANDLE
STD_INPUT_HANDLE contains CONIN$(Console input) as an environment variable,
STD_OUTPUT_HANDLE contains CONOUT$(Console Output) as an environment variable.
Operating system have also the concept of redirection using the given API
BOOL SetStdHandle(DWORD nStdHandle, HANDLE hHandle);
It also return true if calls succeed and return false in case of fail.
Topic 22: Copying multiple files using windows API
Reading Content:
We will see in this module how to display files using cosonle APIs of windows,
in other words display file on screen is actually copying file on console. For this
we made utility function “options()”. We will also use this function further. This
function take a variable list of parameters and use to parse these variable list.
Basically we specify the list of parameters of a program on command prompt,
there are number of options in it. Option () is use to parse these options. It
identify the “-“ prefix and check all the possible options, and set the flag
against the set options.
Following is the code of the program
#include “Everything.h”
#include <stdarg.h>
DWORD Options (int argc, LPCTSTR argv [], LPCTSTR OptStr, …) /*… show the
parameters list are variables */
Va_list pFlagList;
LPBOOL pFlag;
Int iFlag = 0, iArg;
Va_start (pFlagList, OptStr);
While ( (pFlag= Va)arg (pFlagList, LPBOOL)) != NULL
&& iFlag<(int)_tcslen (OptStr)){
*pFlag= False;
For (iArg= 1; !(*(pFlag) && iArg <argc &&argv[iARG] [0]== _T(‘-‘); iArg++)
*pFlag = _memtchr (argv [iArg], OptStr [iFlag], _tcslen (argv [iArg]))!=
NULL
iFlag++;
Va_end (pFlagList);
For (iArg= 1; !(*(pFlag) && iArg <argc &&argv[iARG] [0]== _T(‘-‘); iArg++);
Retrun iArg;
This utility or program takes the number of parameters through command
prompt, in which we specify option and file names. The Files names which are
given , it open these file and try to print the content of these file on console
and if no file name is given then it take the data from standard input and send
to the standard output. It also use report error function in case of any error
occur.
CatFile Function:
Static VOID CatFile (HANDLE hInFile, HANDLE hOutFile)
DWORD nIn, nOut;
BYTE buffer [BUF_SIZE];
While (ReadFile(hInFile, buffer, BUF_SIZE, $nIn, NULL) && (nIn !=0 )
&& WriteFile (hOutFile, buffer, nIn, &Out, NULL));
Return;
}
Topic 23 : Encrypting files
Reading Content:
Encryption is a very old technique, and roman empire use to encrypt secret
conversation in war days and they use Ceasar Cipher algorithm to encrypt. In
this method an alphabet is substituted by another alphabet placed n positions
forward in circular manner. The text that is changed using encryption method is
called Cipher text.
The text that we are going to encrypt is called plain text so it is denoted by P
and after encrypt we present it with C.
File Encryption Program
● if n=1 then A will be replaced by B, B will be replaced by C and so on
uptil Z which will be again replaced by A.
● if n=2 then A will be replaced by C, B will be replaced by Dand so on uptil
Y which will be again replaced by A
● it uses the function C= (P + n) mod 26
We take mod 26 because total character are 26.
We use mod 256 because of ASCII character
File Encryption Program
● The program uses a slightly different version of Ceasar Cipher adapted
for ASCII characters
● C = (P + n) mod 256
This technique is not exactly cipher but little bit similar to cipher. Following is
the code of encrypting file
#include "Everything.h"
#include <io.h>
BOOL cci_f (LPCTSTR, LPCTSTR, DWORD);
int _tmain (int argc, LPTSTR argv [])
if (argc != 4)
ReportError (_T ("Usage: cci shift file1 file2"), 1, FALSE);
if (!cci_f (argv [2], argv [3], _ttoi(argv[1])))
ReportError (_T ("Encryption failed."), 4, TRUE);
return 0;
BOOL cci_f (LPCTSTR fIn, LPCTSTR fOut, DWORD shift)
HANDLE hIn, hOut;
DWORD nIn, nOut, iCopy;
BYTE buffer [BUF_SIZE], bShift = (BYTE)shift;
BOOL writeOK = TRUE;
hIn = CreateFile (fIn, GENERIC_READ, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hIn == INVALID_HANDLE_VALUE) return FALSE;
hOut = CreateFile (fOut, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hOut == INVALID_HANDLE_VALUE) {
CloseHandle(hIn);
return FALSE;
}
while (writeOK && ReadFile (hIn, buffer, BUF_SIZE, &nIn, NULL) && nIn > 0) {
for (iCopy = 0; iCopy < nIn; iCopy++)
buffer[iCopy] = buffer[iCopy] + bShift;
writeOK = WriteFile (hOut, buffer, nIn, &nOut, NULL);
CloseHandle (hIn);
CloseHandle (hOut);
return writeOK;
Topic 24: File and Directory Management
Reading Content:
We will see in this module the types of API for file management. Windows
provides lots of function for file and directory management. These functions
are pretty straightforward and easy to use.
• Such functions perform operations like
• Delete
• Copy
• Rename
Delete
Delete function will help to delete the file on a given path. For deleting file
the following API is used.
BOOL DeleteFile(LPCTSTR lpFileName) ;
Returns TRUE if the file at the given valid file path is deleted
Copy
For copying file the following API is used .
BOOL CopyFile( LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL
bFailIfExists );
Copies an existing file from lpExistingFileName path to lpNewFileName, If
new filename is same as existing then the file is overwritten only if
bFailIfExists is false. It returns TRUE if the file at the given file is copied
successfully
Hard Copy
Windows also provides hardlinks. Following API is used for creating
hardlinks
BOOL CopyHardLink(LPCTSTR lpFileName, LPCTSTR lpExistingFileName,
LPSECURITY_ATTRIBUTES lpSecurityAttributes );
Creates a hard link for existing file
Both the files must be on same system volume
Security attributes will apply on new file name
Move
Use the following APIs to move files
BOOL MoveFile( LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName);
BOOL MoveFileEx( LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName,
DWORD dwFlags );
MoveFile() fails if new file already exists. We use MoveFileEx() to overwrite
existing file.
MoveFileEx() is the extended version of MoveFile() It can be used for both
files and directories
Topic 25: Directory Management
We will discuss the functions which we can use for directory management. We
will do different directory operation like create directory , remove directory and
move directory.
For create directory we will use the following function
BOOL CreateDirectory(LPCTSTR lpPathName,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
For remove directory we will use the following function
BOOL RemoveDirectory(
LPCSTR lpPathName
);
• lpPathName specifies the path of the directory to be created or deleted.
Current Directory
In windows and many other operating system concept of current directory or
current working directory is also exist. Each Process has a current working
directory which can be changed/retrieved using the following API
BOOL SetCurrentDirectory(
LPCTSTR lpPathName
);
DWORD GetCurrentDirectory(
DWORD nBufferLength,
LPTSTR lpBuffer
);
Topic 27: Printing and Prompting on Console
In the previous module we see the certain APIs , which perform input/output
operations on console, now we use these APIs. We create two types of utility
functions, one is help us to display string on console and other is pass some
message to user and also take input from users. Following are names and
description of these functions.
Variable parameter list
●PrintStrings() function is designed which take variable list of parameters.
●Variable parameter list is processed using va_start(), va_arg()and va_end()
library functions
Console Prompt functions:
● This function devised such that it prompt a given message to the user
on console
● Further it also receives user response through the console
Print String Function:
#include "Everything.h"
#include <stdarg.h>
BOOL PrintStrings (HANDLE hOut, ...){
DWORD msgLen, count;
LPCTSTR pMsg;
va_list pMsgList; /* Current message string. */
va_start (pMsgList, hOut); /* Start processing msgs. */
while ((pMsg = va_arg (pMsgList, LPCTSTR)) != NULL) { // read variable
list
msgLen = lstrlen (pMsg); // message length
if (!WriteConsole (hOut, pMsg, msgLen, &count, NULL) // in case of write
console fail
&& !WriteFile (hOut, pMsg, msgLen * sizeof (TCHAR),
&count, NULL)) {
va_end (pMsgList);
return FALSE;
va_end (pMsgList);
return TRUE;
BOOL PrintMsg (HANDLE hOut, LPCTSTR pMsg){
return PrintStrings (hOut, pMsg, NULL);
Console Prompt Function
BOOL ConsolePrompt (LPCTSTR pPromptMsg, LPTSTR pResponse, DWORD
maxChar, BOOL echo){
HANDLE hIn, hOut;
DWORD charIn, echoFlag;
BOOL success;
// create console input file
hIn = CreateFile (_T("CONIN$"), GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// create console output file
hOut = CreateFile (_T("CONOUT$"), GENERIC_WRITE, 0,
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
/* Should the input be echoed? */
echoFlag = echo ? ENABLE_ECHO_INPUT : 0;
success = SetConsoleMode (hIn, ENABLE_LINE_INPUT | echoFlag |
ENABLE_PROCESSED_INPUT)
&& SetConsoleMode (hOut, ENABLE_WRAP_AT_EOL_OUTPUT |
ENABLE_PROCESSED_OUTPUT)
&& PrintStrings (hOut, pPromptMsg, NULL)
&& ReadConsole (hIn, pResponse, maxChar - 2, &charIn,
NULL);
/* Replace the CR-LF by the null character. */
if (success)
pResponse [charIn - 2] = _T('\0');
else
ReportError (_T("ConsolePrompt failure."), 0, TRUE);
CloseHandle (hIn);
CloseHandle (hOut);
return success;
Topic 28:
In this module we will see a small code which will use get current directory.
Printing Current Directory
This example uses the GetCurrentDirectory() function to get the current
directory, further it uses the console IO to print the path.
#include "Everything.h"
#define DIRNAME_LEN (MAX_PATH + 2)
int _tmain (int argc, LPTSTR argv [])
{
TCHAR pwdBuffer [DIRNAME_LEN];
DWORD lenCurDir;
//calling getcurrent directory and name stored in pwdbuffer
lenCurDir = GetCurrentDirectory (DIRNAME_LEN, pwdBuffer);
if (lenCurDir == 0) // in case of failure
ReportError (_T ("Failure getting pathname."), 1, TRUE);
if (lenCurDir > DIRNAME_LEN)
ReportError (_T ("Pathname is too long."), 2, FALSE);
PrintMsg (GetStdHandle (STD_OUTPUT_HANDLE), pwdBuffer); // in case of
correction
return 0;
Topic 29:
If we see historically, there were some file system which was of 12-bit after that
we have 32-bit system and still somewhere 32-bit file system are used. FAT
based system allowed a maximum file size of 232 bytes which is 4GB. NTFS
theoretically provides the file size limit of 264 which is very huge.
Files of such proportion are called huge files. Although for most of the
application 32 bit file space is sufficient. However due to rapid technological
changes leading to increased disk spaces its useful to know how to deal with 64
bit huge file spaces and windows facilitate with some API’s that support 64-bit
file system.
Topic 30:
File Pointer APIs
Whenever a file is opened using CreateFile() the file pointer is placed at the start
of file. The file pointer changes as ReadFile() or WriteFile() operations are
performed. Every subsequent read/write operation is performed at the current
file pointer position.
SetFilePointer() and SetFilePointerEx() functions are used to change file pointer
position. For random file accessSetFilePointer() is clumsy to used for 64 bit
operations. SetFilePointerEx() can be more readily used for 64 bit operations
Use of SetFilePointer() used is difficult as compared to SetFilePointerEx().
SetFilePointer()
DWORD SetFilePointer(
HANDLE hFile,
LONG lDistanceToMove, // for 32-bit file
PLONG lpDistanceToMoveHigh, // pointer to a long for NTFS
DWORD dwMoveMethod
);
hFile
A handle to the file.
lDistanceToMove
The low order 32-bits of a signed value that specifies the number of bytes to
move the file pointer.
lpDistanceToMoveHigh
A pointer to the high order 32-bits of the signed 64-bit distance to move.
dwMoveMethod
The starting point for the file pointer move.
FILE_BEGIN // file pointer move number of bytes w.r.t the start of file
FILE_CURRENT // file pointer move with respect to the current position
FILE_END // file pointer move w.r.t the end of file
Topic 31:
For large files that may have size 264 , we need to understand the 64 bit
arithmetic. To facilitate 64-bit integer arithmetic windows provide a union
LARGE_INTEGER. This union has structure for dealing with lower and higher
double words Moreover it also has a field to deal with whole quadword of type
LONGLONG.
Definition of Structure of large integer
typedef union _LARGE_INTEGER {
struct {
DWORD LowPart;
LONG HighPart;
};
struct {
DWORD LowPart;
LONG HighPart;
} u;
LONGLONG QuadPart;
} LARGE_INTEGER;
Extension of SetFilePointerEx
BOOL SetFilePointerEx(
HANDLE hFile,
LARGE_INTEGER liDistanceToMove,
PLARGE_INTEGER lpNewFilePointer,
DWORD dwMoveMethod
);
hFile
A handle to the file. The file handle must have been created with the
GENERIC_READ or GENERIC_WRITE access right
liDistanceToMove
The number of bytes to move the file pointer.
lpNewFilePointer
A pointer to a variable to receive the new file pointer.
dwMoveMethod
he starting point for the file pointer move.
FILE_BEGIN
FILE_CURRENT
FILE_END
Topic 32:
Overlap structure is a structure which is defined in the ‘windows.h’ and can be
used with read file and write file API’s. This structure can also be used to set file
pointer position, Although the name is overlapped but it is not necessary that
can used only for overlapped operations, we also used in multitasking.
SetFilePointer() or SetFilePointerEx() need not be invoked we can achieve this
goal using readfile and write file. Also, you can append to the file by specifying
0xffffffff in both Offset and OffsetHigh fields
Definition of Overlap structure:
typedef struct _OVERLAPPED {
ULONG_PTR Internal; // reserved filed
ULONG_PTR InternalHigh; // reserved filed
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
} DUMMYSTRUCTNAME;
PVOID Pointer;
} DUMMYUNIONNAME;
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;
Implementation:
filePos.QuadPart=x; // large integer variable
ov.Offset=filePos.LowPart; // place low part of file position
ov.OffsetHigh=filePos.HighPart; // place high part of file position
ReadFile(hFile, buf, sizeof(buf), &nRead, &ov);
…..
WriteFile(hFile, buf, sizeof(buf), &nWrite, &ov);
Topic 33:
One method of getting file size is already exist and that is to open a file first
using create file, once file is open the file pointer is pointing to the first byte
then we move file pointer to the end of file (eof). So file pointer is move from
starting to end of file is give use the size of the file. Windows also provides an
API to get file size GetFileSizeEx()
GetFileSizeEx()
BOOL GetFileSizeEx(
HANDLE hFile,
PLARGE_INTEGER lpFileSize
);
hFile
A handle to the file. The handle must have been created with the
FILE_READ_ATTRIBUTES access right
lpFileSize
A pointer to a LARGE_INTEGER structure that receives the file size, in bytes.
Windows also give option to set the size. The file size can also be changed,
reducing the file size truncate data. Increasing the file size can be useful where
the size of file is expected to grow. We use SetEndOfFileEx() to change the file
size.
Topic 34:
In this topic we discuss the example of creates a file with a capacity of specified
records. The file has a header followed by equal size records. The feature of
this example is, user can modify any record randomly and get the total count of
records in the file.
#include "Everything.h"
#define STRING_SIZE 256
typedef struct _RECORD { /* File record structure */
DWORD referenceCount; /* 0 meands an
empty record */
SYSTEMTIME recordCreationTime;
SYSTEMTIME recordLastRefernceTime;
SYSTEMTIME recordUpdateTime;
TCHAR dataString[STRING_SIZE];
} RECORD;
typedef struct _HEADER { /* File header descriptor */
DWORD numRecords;
DWORD numNonEmptyRecords;
} HEADER;
int _tmain (int argc, LPTSTR argv[])
HANDLE hFile;
LARGE_INTEGER currentPtr;
DWORD OpenOption, nXfer, recNo;
RECORD record;
TCHAR string[STRING_SIZE], command, extra;
OVERLAPPED ov = {0, 0, 0, 0, NULL}, ovZero = {0, 0, 0, 0, NULL};
HEADER header = {0, 0};
SYSTEMTIME currentTime;
BOOLEAN headerChange, recordChange;
int prompt = (argc <= 3) ? 1 : 0;
if (argc < 2)
ReportError (_T("Usage: RecordAccess file [nrec [prompt]]"), 1, FALSE);
OpenOption = ((argc > 2 && _ttoi(argv[2]) <= 0) || argc <= 2) ?
OPEN_EXISTING : CREATE_ALWAYS;
hFile = CreateFile (argv[1], GENERIC_READ | GENERIC_WRITE,
0, NULL, OpenOption, FILE_FLAG_RANDOM_ACCESS,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
ReportError (_T("RecordAccess error: Cannot open existing file."), 2,
TRUE);
if (argc >= 3 && _ttoi(argv[2]) > 0) {
header.numRecords = _ttoi(argv[2]);
if (!WriteFile(hFile, &header, sizeof (header), &nXfer,
&ovZero))
ReportError (_T("RecordAccess Error: WriteFile
header."), 4, TRUE);
currentPtr.QuadPart = (LONGLONG)sizeof(RECORD) *
_ttoi(argv[2]) + sizeof(HEADER);
if (!SetFilePointerEx (hFile, currentPtr, NULL, FILE_BEGIN))
ReportError (_T("RecordAccess Error: Set
Pointer."), 4, TRUE);
if (!SetEndOfFile(hFile))
ReportError (_T("RecordAccess Error: Set End of
File."), 5, TRUE);
if (prompt) _tprintf (_T("Empty file with %d records
created.\n"), header.numRecords);
return 0;
if (!ReadFile(hFile, &header, sizeof (HEADER), &nXfer, &ovZero))
ReportError (_T("RecordAccess Error: ReadFile header."),
6, TRUE);
if (prompt) _tprintf (_T("File %s contains %d non-empty records
of size %d.\n Total capacity: %d\n"),
argv[1], header.numNonEmptyRecords, sizeof(RECORD),
header.numRecords);
while (TRUE) {
headerChange = FALSE; recordChange = FALSE;
if (prompt) _tprintf (_T("Enter
r(ead)/w(rite)/d(elete)/qu(it) record#\n"));
_tscanf (_T("%c%u%c"), &command, &recNo, &extra);
if (command == _T('q')) break;
if (recNo >= header.numRecords) {
if (prompt) _tprintf (_T("record Number is too
large. Try again.\n"));
continue;
currentPtr.QuadPart = (LONGLONG)recNo *
sizeof(RECORD) + sizeof(HEADER);
ov.Offset = currentPtr.LowPart;
ov.OffsetHigh = currentPtr.HighPart;
if (!ReadFile (hFile, &record, sizeof (RECORD), &nXfer,
&ov))
ReportError (_T("RecordAccess: ReadFile failure."),
7, FALSE);
GetSystemTime (¤tTime); /* Use to update record
time fields */
record.recordLastRefernceTime = currentTime;
if (command == _T('r') || command == _T('d')) { /* Report record contents, if
any */
if (record.referenceCount == 0) {
if (prompt) _tprintf (_T("record
Number %d is empty.\n"), recNo);
continue;
} else {
if (prompt) _tprintf (_T("record
Number %d. Reference Count: %d \n"),
recNo, record.referenceCount);
if (prompt) _tprintf (_T("Data: %s\n"),
record.dataString);
/* Exercise: Display times. See ls.c for an
example */
if (command == _T('d')) { /* Delete the record */
record.referenceCount = 0;
header.numNonEmptyRecords--;
headerChange = TRUE;
recordChange = TRUE;
} else if (command == _T('w')) { /* Write the record, even if for the first time */
if (prompt) _tprintf (_T("Enter new data string for
the record.\n"));
_fgetts (string, sizeof(string), stdin); // Don't use
_getts (potential buffer overflow)
string[_tcslen(string)-1] = _T('\0'); // remove the
newline character
if (record.referenceCount == 0) {
record.recordCreationTime =
currentTime;
header.numNonEmptyRecords++;
headerChange = TRUE;
record.recordUpdateTime = currentTime;
record.referenceCount++;
_tcsncpy (record.dataString, string,
STRING_SIZE-1);
recordChange = TRUE;
} else {
if (prompt) _tprintf (_T("command must be r, w,
or d. Try again.\n"));}
/* Update the record in place if any record contents
have changed. */
if (recordChange && !WriteFile (hFile, &record, sizeof
(RECORD), &nXfer, &ov))
ReportError (_T("RecordAccess: WriteFile update
failure."), 8, FALSE);
/* Update the number of non-empty records if required
*/
if (headerChange) {
if (!WriteFile (hFile, &header, sizeof (header),
&nXfer, &ovZero))
ReportError (_T("RecordAccess: WriteFile
update failure."), 9, FALSE);
if (prompt) _tprintf (_T("Computed number of non-empty
records is: %d\n"), header.numNonEmptyRecords);
if (!ReadFile(hFile, &header, sizeof (HEADER), &nXfer, &ovZero))
ReportError (_T("RecordAccess Error: ReadFile header."),
10, TRUE);
if (prompt) _tprintf (_T("File %s NOW contains %d non-empty
records.\nTotal capacity is: %d\n"),
argv[1], header.numNonEmptyRecords,
header.numRecords);
CloseHandle (hFile);
return 0;
}
Topic 35:
Windows provide a certain set of APIs for search files/folders within the hierarchical
structure of Directories/folders. These APIs include:
FindFirstFile(), FindFirstFileEx(), FindNextFile() and FindClose(). Detail of these APIs are:
FindFirstFile() API
Handle FindFirstFile(LPCSTR lpFileName, LPWIN32_FIND_DATA A lpFindFileData);
Where lpFileName represents the directory or path, and the filename. The name can
include wildcard characters, for example, an asteristk (*) or a question mark (?).
lpFindFileData: A pointer to the WIN32_FIND_DATA structure that receives
information about a found file or directory.
Structure or Detail of WIN32_FIND_DATA structure:
typedef struct _WIN32_FIND_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
CHAR cFileName[Max_Path];
CHAR cAlternateFileName[14];
DWORD dwFileType;
DWORD dwCreatorType;
DWORD WFinderFlags;
};
FindNextFile() API:
BOOL FindNextFile(HANDLE hFindFile, LPWIN32_FIND_DATA A lpFindFileData );
Where hFindFile represents the search handle returned by a previous call to the
FindFirstFile or FindFirstFileEx function &
lpFindFileData is a pointer to the WIN32_FIND_DATA structure that receives
information about the found file or sub-directory.
FindClose() API
BOOL FindClose(HANDLE hFindFile);
Topic 36:
Certain other APIs are also used for getting the file attributes but these API need to
have an open file handle rather than scan a directory or use a filename.
GetFileTime() API
BOOL GetFileTime(HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME
lpLastAccessTime, LPFILETIME lpLastWriteTime);
Where hFile is a handle to the file or directory.
lpCreationTime is a pointer to a FILETIME structure to receive the data and time the file
or directory was created.
lpLastAccessTime is a pointer to a FILETIME structure to receive the data and time the
file or directory was last accessed.
lpLastWriteTime is a pointer to a FILETIME structure to receive the data and time the
file or directory was last written to truncated or overwritten.
FileTimeToSystemTime() API
It converts the file time into system time.
SystemTimeToFileTime() API
It converts the system time into file time.
CompareFileTime() API
It compares file times of two files. It returns -1 if less, 0 if equal and +1 if greater.
SetFileTime() API
It sets the three time of file. NULL used if the file time is not to be changed.
FileTimeToLocalFileTime() and LocalFileTimeToFileTime() APIs converts UTC and local
File time.
GetFileType API
It provides information regarding the type of file (disk file or pipes)
GetFileAttributes() API
DWORD GetFileAttributes(LPCTSTR lpFileName);
Where lpFileName is the name of a file or directory. Its return value is:
FILE_ATTRIBUTE_DIRECTORY, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_NORMAL,
FILE_ATTRIBUTE_TEMPORARY.
In case of failure, the return value is INVALID_FILE_ATTRIBUTES whose value is
0xFFFFFFFF.
Topic 37:
Windows provide the facility of creating temporary files for storing the intermediate
results. These files are assigned unique names in a directory with extension .tmp.
Certain APIs are used for creating temporary files. These include:
GetTempFileName API
UINT GetTempFileName(LPCTSTR lpPathName, LPCTSTR lpPrefixString, UINT uUnique,
LPSTR lpTempFileName);
Where lpPathName represents the directory path for the filename. The string cannot be
longer than 14 characters.
lpPrefixString represents the null-terminated prefix string. The first 3 characters of
this string is used as a prefix of the filename.
uUnique represents an unsigned integer to be used in creating the temporay filename.
lpTempFileName is a pointer to the buffer that receives the temporary filename
Topic 38:
We can get the attributes of a file, listing of files and can traverse the directory
structure using certain windows APIs.
An application called lsW is used for showing files and listing their attributes. It uses
two option switched that is –l and –R where –l option is used to list the attributes of
files in a folder and –R is used for recursive traversal through subfolders.
This application or program will work with a relative pathname; it will not work with
absolute pathname.
Program: File Listing and Directory Traversal
#include<everything.h>
BOOL TraverseDirectory(LPTSTR, LPTSTR, DWORD, LPBOOL);
DWORD FileType(LPWIN32_FIND_DATA);
BOOL ProcessItem(LPWIN32_FIND_DATA, DWORD, LPBOOL);
Int _tmain(int argc, LPTSTR argv[])
BOOL flags[MAX_OPTIONS], ok=TRUE;
TCHAR searchPattern[MAX_PATH +1], currPath[MAX_PATH_LONG +1],
parrentPath[MAX_PATH_LONG +1];
LPTSTR pSlash, pSearchPattern;
int i, fileIndex;
DWORD pathLength;
fileIndex = Options(argc, argv, _T(“RI”), &flags[0], &flags[1], NULL);
/* parse the search pattern into two parts: the parent and the filename or wild card
expression. The filename is the longest suffix not containing a slash. The parent is the
remaining prefix with a slash. This is performed for all command line search pattern. If
no file is specified, use * as the search pattern */
pathLength = getCurrentDirectory(MAX_PATH_LONG, currPath);
if(pathLength==0 || pathLength>= MAX_PATH_LONG)
{ /* pathLength>= MAX_PATH_LONG (32780) should be impossible */
ReportError(_T(“GetCurrentDirectory failed”, 1, TRUE);