Topic 20-38

Download as pdf or txt
Download as pdf or txt
You are on page 1of 35

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 (&currentTime); /* 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);

You might also like