|< C Storage Class & Memory Functions | Main | C Run-Time 2 >| Site Index | Download |


 

 

 

MODULE A

IMPLEMENTATION SPECIFIC

MICROSOFT C Run-Time Win32 1

 

 

 

My Training Period: aa hours. Before you begin, read some instruction here.

 

 

What are in this Module?

  1. The Background Story: The Microsoft C Run-time Libraries

  2. The Standard C++ Library

  3. The Run-Time Functions

  4. Directory Management

  5. Directory Management Functions

  6. Program Examples

 

 

 

 

The skills that supposed to be acquired:

  1. Able to recognize the standard C and implementation specific.

  2. Able to grasp the fundamental of the Windows file system, file and directory.

  3. Able to find and collect the needed information in order to use functions to accomplish your tasks.

  4. Able to understand and use functions that available in the libraries in your own programs.

  • In this Module you will be introduced to the absolute implementation specific of the C, the Microsoft C.  However it is still non-GUI type of programs :o).

  • This brings you to the specific use of the compilers that compile the Windows applications and the programs developed are specific to be run on the Windows platform although in the discussion and program examples of this Module and later on, the standard and non standard (Microsoft extension) libraries will be used together.

  • Make sure you have already fluent in functions because we will learn how to use them.  Remember all the thing about a function such as parameters, return values etc.  The final purpose of this Module and that follows actually to show you how to find and collect all the required information from tons of the documentations to suit your needs in developing programs.

  • Keep in mind that, normally, in libraries we have the following things which defined in and accessed through the header files:

  1. Macro definitions.

  2. Function prototypes.

  3. Structure definitions (struct).

  4. Enumeration definitions (enum).

  5. Data type definitions.

  6. The typedef usage.

  • For the data type and structure definitions, you will find that use of struct, typedef and enum is normal here and also for Win32 programming (will be discussed in another Module).

  • To better understand you must be fluent on those things.  If you encounter any problem, you might have to go back to basic :o) by referring to tenouk.com. Other pre requirement topics include array and pointer.

The Background Story: The Microsoft C Run-time Libraries

  • The following table lists a various .lib files that comprise the C run-time (CRT) libraries as well as their associated compiler options and preprocessor directives.  The libraries contain the C run-time library functions.

  • For these libraries, the header files used in the programs must have the .h extension.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Pure C run-time library

Characteristics

Compiler Option

Preprocessor directives

LIBC.LIB

Single-threaded, static link.

/ML

-

LIBCMT.LIB

Multithreaded, static link.

/MT

_MT

MSVCRT.LIB

Multithreaded, dynamic link (import library for MSVCR70.DLL).  Be aware that if you use the Standard C++ Library, your program will need MSVCP70.DLL to run.

/MD

_MT, _DLL

LIBCD.LIB

Single-threaded, static link (debug).

/MLd

_DEBUG

LIBCMTD.LIB

Multithreaded, static link (debug).

/MTd

_DEBUG, _MT

MSVCRTD.LIB

Multithreaded, dynamic link (import library for MSVCR70D.DLL) (debug)

/MDd

_DEBUG, _MT, _DLL

 

Table 1: C run-time libraries

invoking the C++ project property page through Visual Studio menus

 

Figure 0

Invoking the Visual Studio C++ project property page

 

Figure 1

 

 

Visual C++ .Net project property settings page

 

Figure 2.

The Standard C++ Library

Old iostream library

Characteristics

Compiler Option

Preprocessor directives

LIBCI.LIB

Single-threaded, static link.

/ML

-

LIBCIMT.LIB

Multithreaded, static link.

/MT

_MT

MSVCIRT.LIB

Multithreaded, dynamic link (import library for MSVCI70.DLL).

/MD

_MT, _DLL

LIBCID.LIB

Single threaded, static link.

/MLd

_DEBUG

LIBCIMTD.LIB

Multithreaded, static link.

/MTd

_DEBUG, _MT

MSVCIRTD.LIB

Multithreaded, dynamic link (import library for MSVCI70D.DLL).

/MDd

_DEBUG, _MT, _DLL

 

Table 2: Old iostream libraries

Standard C++ Library

Characteristics

Compiler Option

Preprocessor directives

LIBCP.LIB

Single-threaded, static link

/ML

 -

LIBCPMT.LIB

Multithreaded, static link

/MT

_MT

MSVCPRT.LIB

Multithreaded, dynamic link (import library for MSVCP70.dll)

/MD

_MT, _DLL

LIBCPD.LIB

Single-threaded, static link

/MLd

_DEBUG

LIBCPMTD.LIB

Multithreaded, static link

/MTd

_DEBUG, _MT

MSVCPRTD.LIB

Multithreaded, dynamic link (import library for MSVCP70.DLL)

/MDd

_DEBUG, _MT, _DLL

 

Table 3: Standard C++ libraries

  1. If you include a Standard C++ Library header in your code, a Standard C++ Library will be linked in automatically by Visual C++ at compile time. For example:

#include <ios>
  1. If you include an old iostream library header, an old iostream library will be linked in automatically by Visual C++ at compile time. For example:
#include <ios.h>

The Run-Time Functions

  1. What is the use of the function?  This will match with "what are you going to do or create?"  Keep in mind that to accomplish some of the tasks you might need more (several) than one function.  For example:

_chsize() used to change the file size.

  1. What is the function prototype, so we know how to write (call) a proper syntax of the function.  For example:
int _chsize(int handle, long size);
  1. From the function prototype, how many parameters, the order and what are their types, so we can create the needed variables.  For example:

handle

Handle referring to open file.

size

New length of file in bytes.

  1. What header files need to be included?  For example the _chsize needs:

<io.h>

  1. What is the return type and value?  For example:

_chsize() returns 0 if the file size is successfully changed.  A return value of –1 indicates an error: errno is set to EACCES if the specified file is locked against access, to EBADF if the specified file is read-only or the handle is invalid, or to ENOSPC if no space is left on the device.

 

--------------------The Story and Program Examples---------------------

 

 

Directory Management

Directory Management Functions

Function

Use

_chdir(), _wchdir()

Change current working directory.

_chdrive()

Change current drive.

_getcwd(), _wgetcwd()

Get current working directory for default drive.

_getdcwd(), _wgetdcwd()

Get current working directory for specified drive.

_getdiskfree()

Populates a _diskfree_t structure with information about a disk drive.

_getdrive()

Get current (default) drive.

_getdrives()

Returns a bitmask representing the currently available disk drives.

_mkdir(), _wmkdir()

Make new directory.

_rmdir(), _wrmdir()

Remove directory.

_searchenv(), _wsearchenv()

Search for given file on specified paths.

 

Table 4:  Directory control functions

Information

Description

The function

_getdrives().

The use

Returns a bitmask representing the currently available disk drives.

The prototype

int _getdrives(void);

Example

ULONG DriveMask = _getdrives();

 

while (DriveMask)

{ // list all the drives...

  if(DriveMask & 1)

    printf(mydrives);

    ++mydrives[1];

    // shift the bit masks binary to the right and repeat

    DriveMask >>= 1;

}

The parameters

void

The return value

If the function succeeds, the return value is a bitmask representing the currently available disk drives. Bit position 0 (the least-significant bit) is drive A, bit position 1 is drive B, bit position 2 is drive C, and so on. If the function fails, the return value is zero. To get extended error information, call GetLastError().

The header file

<direct.h>

 

Table 5:  _getdrives() information

#include <windows.h>

#include <direct.h>

#include <stdio.h>

#include <tchar.h>

 

// buffer, be careful with terminated NULL. Must match with ++mydrives[1]...that is one space

// for example if no one space: "A:"--> ++mydrives[0];

// you may try char mydrives[ ] = {" A: "}; or char mydrives[ ] = " A: ";

TCHAR mydrives[ ] = " A: ";

 

int main()

{

   // get the drives bit masks...1 is available, 0 is not available A = least significant bit...

   ULONG DriveMask = _getdrives();

   // if something wrong

   if(DriveMask == 0)

      printf("_getdrives() failed with failure code: %d\n", GetLastError());

   else

   {

     printf("This machine has the following logical drives:\n");

     while (DriveMask)

     {   // list all the drives...

         if(DriveMask & 1)

            printf(mydrives);

         // go to the next drive strings with one space

         ++mydrives[1];

         // shift the bit masks binary to the right and repeat

         DriveMask >>= 1;

      }

  printf("\n");

}

   return 0;

}

 

The output:

 

This machine has the following logical drives:

 A:  C:  D:  E:  F:  G:  H:  I:  J:  K:  L:

Press any key to continue

  • The following is an example of the needed information in order to use the  _getdiskfree() function.

Information

Description

The function

_getdiskfree().

The use

Populates a _diskfree_t structure with information about a disk drive.

The prototype

unsigned _getdiskfree( unsigned drive, struct _diskfree_t * driveinfo);

Example

struct _diskfree_t df = {0};

unsigned uDrive;

_getdiskfree(uDrive, &df);

The parameters

drive - The disk drive for which you want information.

driveinfo - A _diskfree_t structure that will be populated with information about the drive.  _diskfree_t is defined in direct.h.

The return value

If the function succeeds, the return value is zero. If the function fails, the return value is the error code. To get extended error information, call GetLastError().

The header file

<direct.h>

 

Table 6:  _getdiskfree() information

#include <windows.h>

#include <direct.h>

#include <stdio.h>

#include <tchar.h>

 

TCHAR g_szText[ ]  = _T("Drive Total_clus Available_clus Sec/Cluster Bytes/Sec\n");

TCHAR g_szText1[ ] = _T("----- ---------- -------------- ----------- ---------\n");

TCHAR g_szInfo[ ]  = _T("->                                                   \n");

 

// ...for data display format...

// right justified, thousand comma separated and other format for displayed data

void utoiRightJustified(TCHAR* szLeft, TCHAR* szRight, unsigned uValue)

{

   TCHAR* szCur = szRight;

   int nComma = 0;

   if(uValue)

   {

      while(uValue && (szCur >= szLeft))

         {

         if(nComma == 3)

               {

            *szCur = ',';

            nComma = 0;

         }

         else

               {

            *szCur = (uValue % 10) | 0x30;

            uValue /= 10;

            ++nComma;

         }

         --szCur;

      }

   }

   else

   {

      *szCur = '0';

      --szCur;

   }

 if(uValue)

   {

      szCur = szLeft;

      while(szCur <= szRight)

         { // if not enough field to display the data...

         *szCur = '*';

         ++szCur;

      }

   }

}

 

int main()

{

   TCHAR szMsg[4200];

   struct _diskfree_t df = {0};

   // search drives and assigns the bit masks to uDriveMask variable...

   ULONG uDriveMask = _getdrives();

   unsigned uErr, uLen, uDrive;

   printf("clus - cluster, sec - sector\n");

   // may need a casting from TCHAR to char * here

   // printf((char *)g_szText);

   printf(g_szText);

   printf(g_szText1);

   for(uDrive = 1; uDrive <= 26; ++uDrive)

   {

      // if the drive is available...

      if(uDriveMask & 1)

         { // call _getdiskfree()...

         uErr = _getdiskfree(uDrive, &df);

         // provide some storage

         memcpy(szMsg, g_szInfo, sizeof(g_szInfo));

         szMsg[3] = uDrive + 'A' - 1;

        

         // if _getdiskfree() is no error, display the data

         if(uErr == 0)

               {

            utoiRightJustified(szMsg+4, szMsg+15, df.total_clusters);

            utoiRightJustified(szMsg+18, szMsg+29, df.avail_clusters);

            utoiRightJustified(szMsg+27, szMsg+37, df.sectors_per_cluster);

            utoiRightJustified(szMsg+40, szMsg+50, df.bytes_per_sector);

         }

         else

           {// print system message and left other fields empty

            uLen = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, uErr, 0, szMsg+8, 4100, NULL);

            szMsg[uLen+6] = ' ';

            szMsg[uLen+7] = ' ';

            szMsg[uLen+8] = ' ';

         }

         printf(szMsg);

      }

      // shift right the found drive bit masks and repeat the process

      uDriveMask >>= 1;

   }

   return 0;

}

 

The output sample:

 

clus - cluster, sec - sector

Drive Total_clus Available_clus Sec/Cluster Bytes/Sec

----- ---------- -------------- ----------- ---------

-> A       2,847           834       1          512

-> C   2,560,351        62,315       8          512

-> D   2,560,351     1,615,299       8          512

-> E   2,560,351     2,310,975       8          512

-> F   2,560,351     2,054,239       8          512

-> G   2,353,514     2,039,396       8          512

-> H   2,560,351     2,394,177       8          512

-> I   2,381,628     1,618,063       8          512

-> J     321,935             0       1        2,048

-> L      63,419        20,706      16          512

Press any key to continue

 

Information

Description

The function

_getdrive().

The use

Gets the current disk drive.

The prototype

int _getdrive(void);

Example

int curdrive;

curdrive = _getdrive();

The parameters

void

The return value

Returns the current (default) drive (1=A, 2=B, and so on).  There is no error return.

The header file

<direct.h>

 

Table 7:  _getdrive() information

Information

Description

The function

_chdir(), _wchdir().

The use

Change the current working directory.

The prototype

int _chdir(const char *dirname);

/* for wide character */

int _wchdir(const wchar_t *dirname);

Example

char path1[50] = "C:\\WINNT\\System32\\config";

_chdir(path1);

The parameters

dirname - Path of new working directory.

The return value

These functions return a value of 0 if successful.  A return value of –1 indicates that the specified path could not be found, in which case errno is set to ENOENT.

The header file

<direct.h> or <wchar.h> for _wchdir().

 

Table 8:  _chdir(), _wchdir() functions information

_chdir("c:\\temp");

/*******cruntime.cpp*******/

/***Visual C++ .Net/7.0****/

#include <stdio.h>

#include <conio.h>

#include <direct.h>

#include <stdlib.h>

#include <ctype.h>

 

int main(void)

{

int chr, drive, curdrive;

static char path[_MAX_PATH];

char buffer[_MAX_PATH];

char newdir[50] = "\\testdir";

// char path1[50] = "C:\\Windows\\System32\\config";

char path1[50] = "C:\\WINNT\\System32\\config";

 

/* save current drive. */

curdrive = _getdrive();

printf("Available drives in this machine are: \n");

 

/* if we can switch to the drive, it exists. */

for(drive = 1; drive <= 26; drive++)

if(!_chdrive(drive))

  printf("%c: ", drive + 'A' - 1);

 

printf("\n\nType drive letter to check: ");

chr = _getch();

if(chr == 27)

  printf("Illegal drive input\n");

if(isalpha(chr))

  _putch(chr);

if(_getdcwd(toupper(chr) - 'A' + 1, path, _MAX_PATH) != NULL)

  printf("\nCurrent directory on that drive is:\n%s\n", path);

 

/* restore original drive. */

_chdrive(curdrive);

 

/* get the current working directory */

if(_getcwd(buffer, _MAX_PATH) == NULL)

  perror("_getcwd error");

else

  printf("\nCurrent working directory is: %s\n", buffer);

 

/* create a directory and then delete */

if(_mkdir(newdir) == 0)

{

  printf("\nDirectory %s was successfully created\n", newdir);

  system("dir \\testdir");

 

  if(_rmdir("\\testdir") == 0)

    printf("\nDirectory %s was successfully removed\n", newdir);

  else

    printf("\nProblem removing directory %s\n", newdir);

}

else

   printf("\nProblem creating directory %s\n", newdir);

 

/* uses _chdir() function to verify that a given directory exists */

printf("\n");

printf("Change directory........\n");

if(_chdir(path1))

  printf("Unable to locate the directory: %s\n", path1);

else

  system("dir *.log /a");

printf("\n");

return 0;

}

 

The output:

 

Available drives in this machine are:

C: D: F:

 

Type drive letter to check: c

Current directory on that drive is:

c:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE

 

Current working directory is: D:\mcruntime

 

Directory \testdir was successfully created

 Volume in drive D has no label.

 Volume Serial Number is 90C8-54BB

 

 Directory of D:\testdir

 

05/17/2005  08:54p      <DIR>          .

05/17/2005  08:54p      <DIR>          ..

               0 File(s)              0 bytes

               2 Dir(s)  13,975,789,568 bytes free

 

Directory \testdir was successfully removed

 

Change directory........

 Volume in drive C has no label.

 Volume Serial Number is B03D-C18F

 

 Directory of C:\WINNT\System32\config

 

05/17/2005  08:07p               1,024 default.LOG

05/17/2005  08:08p               1,024 SAM.LOG

05/17/2005  08:17p               1,024 SECURITY.LOG

05/17/2005  08:54p              12,288 software.LOG

06/05/2004  07:06a               1,024 system.LOG

06/05/2004  07:06a                   0 TempKey.LOG

06/05/2004  07:06a               1,024 userdiff.LOG

               7 File(s)         17,408 bytes

               0 Dir(s)   7,208,861,696 bytes free

 

Press any key to continue

/*******cruntime.cpp*******/

/***Visual C++ EE 2005 on Win XP Pro SP 2 ****/

#include <stdio.h>

#include <conio.h>

#include <direct.h>

#include <stdlib.h>

#include <ctype.h>

 

int main(void)

{

    int chr, drive, curdrive;

    static char path[_MAX_PATH];

    char buffer[_MAX_PATH];

    char newdir[50] = "\\testdir";

    // char path1[50] = "C:\\WINNT\\System32\\config";

    char path1[50] = "C:\\Windows\\System32\\config";

    /* save current drive. */

    curdrive = _getdrive();

    printf("Available drives in this machine are: \n");

    /* if we can switch to the drive, it exists. */

    for(drive = 1; drive <= 26; drive++)

        if(!_chdrive(drive))

    printf("%c: ", drive + 'A' - 1);

    printf("\n\nType drive letter to check: ");

    chr = _getch();

    if(chr == 27)

        printf("Illegal drive input\n");

    if(isalpha(chr))

        _putch(chr);

    if(_getdcwd(toupper(chr) - 'A' + 1, path, _MAX_PATH) != NULL)

        printf("\nCurrent directory on that drive is:\n%s\n", path);

    /* restore original drive. */

    _chdrive(curdrive);

    /* get the current working directory */

    if(_getcwd(buffer, _MAX_PATH) == NULL)

        perror("_getcwd error");

    else

        printf("\nCurrent working directory is: %s\n", buffer);

    /* create a directory and then delete */

    if(_mkdir(newdir) == 0)

    {

        printf("\nDirectory %s was successfully created\n", newdir);

        system("dir \\testdir");

        if(_rmdir("\\testdir") == 0)

            printf("\nDirectory %s was successfully removed\n", newdir);

        else

            printf("\nProblem removing directory %s\n", newdir);

    }

    else

        printf("\nProblem creating directory %s\n", newdir);

    /* uses _chdir() function to verify that a given directory exists */

    printf("\n");

    printf("Change directory........\n");

    if(_chdir(path1))

        printf("Unable to locate the directory: %s\n", path1);

    else

        system("dir *.log /a");

    printf("\n");

    return 0;

}

 

A sample output:

C++ sample output for Vsual C++ Express Edition

 

Running sample programs using Visual C++ Express Edition 2005, 2008 and Visual C++ 2005/Visual Studio 2008

The C++ project property page

 

 

Visual C++ Express Edition 2005

 

 

Visual C++ 2005 of the Visual Studio 2005

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Further reading and digging:

  1. Check the best selling C, C++ and Windows books at Amazon.com.
  2. Microsoft Visual C++, online MSDN.
  3. For Multibytes, Unicode characters and Localization please refer to Locale, Wide Character & Unicode (Story) and Windows Users & Groups tutorial (Implementation).
  4. Notation used in MSDN is Hungarian Notation instead of CamelCase and is discussed in C & C++ Notations.

 

 

 

 

 

 

 

|< C Storage Class & Memory Functions | Main | C Run-Time 2 >| Site Index | Download |

Some Old Part of the C-Run Time: Part 1 | Part 2 | Part 3 | Part 4


C & C++ Programming Tutorial | C Programming Practice | Win32 and C with Unicode Version