• Welcome to Powerbasic Museum 2020-B.
 

ProgEx11 - Simple Example of Win Api Calling in C++ - GetCurrentDirectory

Started by Frederick J. Harris, November 06, 2009, 03:34:13 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Frederick J. Harris


/*
  ProgEx11  Can Compile As C Or C++ Program

  We've reached the point where we can finally leave the C runtime functions
  and start playing with the Win32 Api in both C and PowerBASIC.  Why don't
  we dabble at that for awhile, then fool around some with C++ isms.

  A good understanding of memory addressing and C asciiz string minipulation
  is a big help in working with the Win 32 Api because it is entirely C based.
  Windows was largely created before C++ became very mature, so it extensively
  uses techniques such as we've been exploring in the past ten C program
  examples.

  Lets start with a Win Api function now - one that really isn't needed in
  PowerBASIC because PowerBASIC has a built in function for this functionality,
  that is, obtaining the current directory.  Below is the Win32 Api's
  GetCurrentDirectory() function.  We'll try to use it.

  GetCurrentDirectory

  The GetCurrentDirectory function retrieves the current directory for the
  current process.

  DWORD GetCurrentDirectory
  (
   DWORD nBufferLength,  // size, in characters, of directory buffer
   LPTSTR lpBuffer       // pointer to buffer for current directory
  );

  Parameters

  nBufferLength      Specifies the length, in characters, of the buffer for the
                     current directory string. The buffer length must include
                     room for a terminating null character.

  lpBuffer           Pointer to the buffer for the current directory string.
                     This null-terminated string specifies the absolute path to
                     the current directory.

  Return Values

  If the function succeeds, the return value specifies the number of characters
  written to the buffer, not including the terminating null character.

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

  If the buffer pointed to by lpBuffer is not large enough, the return value
  specifies the required size of the buffer, including the number of bytes
  necessary for a terminating null character.

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

  The above help documentation from Microsoft is typical of all Win Api
  functions and to my way of thinking is excellent.  First comes the name of
  the function and a very brief description of what it does.  Following that is
  a listing of the function, its return values and parameters.

  If you've followed my discussions up to this point of C memory buffers,
  allocating memory, and so forth, the above decsciption should make some sense
  to you.  What this function will do for you is return a string of characters
  that represents the full path of the current directory, but before it can do
  that it requires that you provide it with both a memory buffer into which it
  can write the characters, and information on the size of that buffer.  Given
  this information it will either return the desired string to you plus its
  length, or the length it needs if the buffer you supplied to it isn't large
  enough.
*/

#include <windows.h>  //this program won't work in Linux because of windows.h!!!
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main()
{
DWORD dwReturn;                                    //Declare needed variables
char szBuffer[MAX_PATH];                           //Allocate (easily) a buffer
                                                   //using MAX_PATH equate
dwReturn = GetCurrentDirectory(MAX_PATH,szBuffer); //Call Api Function
printf("MAX_PATH     = %u\n", MAX_PATH);           //Output results...
printf("dwReturn     = %u\n", (unsigned int)dwReturn);
printf("szBuffer     = %s\n", szBuffer);
printf("szBuffer     = %u\n", (unsigned int)szBuffer);
printf("&szBuffer[0] = %u\n", (unsigned int)&szBuffer[0]);
getchar();

return EXIT_SUCCESS;
}

/*  --output--
MAX_PATH     = 260
dwReturn     = 41
szBuffer     = C:\Code\Dev-Cpp\Projects\CPrimer\ProgEx11
szBuffer     = 2293328
&szBuffer[0] = 2293328
*/

/*
  As you can see, when you follow the rules everything works out as predictably
  as it should.

  Here are some important little details that may or may not have occurred to
  you.  Note that there are two parameters to this function and of course a
  return value.  The first parameter could be described as an 'input' parameter
  in that we put a value 'in' there for the function to retrieve internally for
  its use.  Of course, that parameter was the size of the buffer we were giving
  it.  However, the second parameter could very well be described as an
  'output' parameter if we were to continue with the same naming logic as with
  the first.  We do put 'in' an address of a buffer for the function to use,
  but the most important result we want from the function is returned to us
  through this second parameter rather than through a function return value.
  This is the case throughout the Win Api.  Data is in the vast majority of
  cases returned through output parameters of functions rather than through
  function return values.  Generally speaking, return values are used to return
  success/failure codes or simple TRUE/FALSE values indicating whether the
  function succeeded or failed.

  The other point worth mentioning here is that we obtained the necessary
  buffer to hold the character array in the easiest way possible; we simply
  declared an uninitialized array at the top of the function large enough to
  hold any string the operating system could throw at us.  This largest size
  might be Windows operating system dependent so an equate 'MAX_PATH' was used
  in place of a hard coded number.  We could have used malloc as with the last
  example to obtain the memory, but in many cases its just easier to declare an
  uninitialized array as done here and let the compiler allocate the memory
  automatically at run time.  There are cases however where this won't work;
  then one must use malloc.  However, if it will work as it does here one would
  be foolish to do it the harder way.

  Finally, note that our declaration of szBuffer looked like this...

  char szBuffer[MAX_PATH];

  szBuffer is indeed an array variable.  C uses square brackets for array
  variables and parentheses for enclosing function arguments.  However, when we
  placed szBuffer in the function call we just used the szBuffer term without
  the brackets.  This is because, as we've mentioned several times previously,
  an array variable without the brackets is a pointer to the base address of
  the allocation for the array, i.e., szBuffer = &szBuffer[0] (remember that
  the '&' symbol is an operator in C that returns the address of whatever it is
  prepended to and is analogous to Basic's Varptr() function - see ProgEx03).
  And since GetCurrentDirectory() specifies a pointer parameter passing
  mechanism - we need to pass the base address of the memory allocation to the
  function.

  Lets now turn to PowerBASIC and see how all this works there.
*/