Merging MinGW changes

This commit is contained in:
Earnie Boyd 2002-05-28 13:13:45 +00:00
parent ad39fa8cb0
commit 4ad1e6fedb
46 changed files with 1877 additions and 1877 deletions

View File

@ -1,3 +1,3 @@
Main test.exe : test.c ;
Main test.exe : test.c ;

View File

@ -1,91 +1,91 @@
/*
* A test which demonstrates the use of opendir and related functions
* declared in dirent.h.
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
int
main (int argc, char* argv[])
{
int i;
struct dirent* de;
DIR* dir;
long lPos;
if (argc == 2)
{
printf ("Opening directory \"%s\"\n", argv[1]);
dir = opendir(argv[1]);
}
else
{
printf ("Opening \".\"\n");
dir = opendir(".");
}
if (!dir)
{
printf ("Directory open failed!\n");
if (errno)
{
printf ("Error : %s\n", strerror(errno));
}
return 1;
}
i = 0;
lPos = -1;
while (de = readdir (dir))
{
i++;
printf ("%d : \"%s\" (tell %ld)\n", i, de->d_name,
telldir(dir));
if (i == 3)
{
printf ("We will seek here later.\n");
lPos = telldir (dir);
}
}
printf ("Rewind directory.\n");
rewinddir (dir);
if (de = readdir (dir))
{
printf ("First entry : \"%s\"\n", de->d_name);
}
else
{
printf ("Empty directory.\n");
}
if (lPos != -1)
{
printf ("Seeking to fourth entry.\n");
seekdir (dir, lPos);
if (de = readdir (dir))
{
printf ("Fourth entry : \"%s\"\n", de->d_name);
}
else
{
printf ("No fourth entry.\n");
}
}
else
{
printf ("Seek position is past end of directory.\n");
}
printf ("Closing directory.\n");
closedir (dir);
}
/*
* A test which demonstrates the use of opendir and related functions
* declared in dirent.h.
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
int
main (int argc, char* argv[])
{
int i;
struct dirent* de;
DIR* dir;
long lPos;
if (argc == 2)
{
printf ("Opening directory \"%s\"\n", argv[1]);
dir = opendir(argv[1]);
}
else
{
printf ("Opening \".\"\n");
dir = opendir(".");
}
if (!dir)
{
printf ("Directory open failed!\n");
if (errno)
{
printf ("Error : %s\n", strerror(errno));
}
return 1;
}
i = 0;
lPos = -1;
while (de = readdir (dir))
{
i++;
printf ("%d : \"%s\" (tell %ld)\n", i, de->d_name,
telldir(dir));
if (i == 3)
{
printf ("We will seek here later.\n");
lPos = telldir (dir);
}
}
printf ("Rewind directory.\n");
rewinddir (dir);
if (de = readdir (dir))
{
printf ("First entry : \"%s\"\n", de->d_name);
}
else
{
printf ("Empty directory.\n");
}
if (lPos != -1)
{
printf ("Seeking to fourth entry.\n");
seekdir (dir, lPos);
if (de = readdir (dir))
{
printf ("Fourth entry : \"%s\"\n", de->d_name);
}
else
{
printf ("No fourth entry.\n");
}
}
else
{
printf ("Seek position is past end of directory.\n");
}
printf ("Closing directory.\n");
closedir (dir);
}

View File

@ -1,22 +1,22 @@
/*
* Source code of the functions inside our test DLL. Note that DllMain is
* not required (it will be provided by the stub in libmingw32.a).
*/
#if 0
#include <windows.h>
#endif
int Add (int x, int y)
{
printf ("In add!\nx = %d\ny = %d\n", x, y);
return (x + y);
}
double __attribute__((stdcall)) Sub (double x, double y)
{
printf ("In sub!\nx = %f\ny = %f\n", x, y);
return (x - y);
}
/*
* Source code of the functions inside our test DLL. Note that DllMain is
* not required (it will be provided by the stub in libmingw32.a).
*/
#if 0
#include <windows.h>
#endif
int Add (int x, int y)
{
printf ("In add!\nx = %d\ny = %d\n", x, y);
return (x + y);
}
double __attribute__((stdcall)) Sub (double x, double y)
{
printf ("In sub!\nx = %f\ny = %f\n", x, y);
return (x - y);
}

View File

@ -1,3 +1,3 @@
EXPORTS
Add
Sub@16
EXPORTS
Add
Sub@16

View File

@ -1,4 +1,4 @@
int Add (int x, int y);
double __attribute__((stdcall)) Sub (double x, double y);
int Add (int x, int y);
double __attribute__((stdcall)) Sub (double x, double y);

View File

@ -1,23 +1,23 @@
#include <stdio.h>
#include "dll.h"
int main()
{
int i, j, k;
double dk;
i = 10;
j = 13;
k = Add(i, j);
printf ("%d + %d = %d\n", i, j, k);
dk = Sub(i, j);
printf ("%d - %d = %f\n", i, j, dk);
return 0;
}
#include <stdio.h>
#include "dll.h"
int main()
{
int i, j, k;
double dk;
i = 10;
j = 13;
k = Add(i, j);
printf ("%d + %d = %d\n", i, j, k);
dk = Sub(i, j);
printf ("%d - %d = %f\n", i, j, dk);
return 0;
}

View File

@ -1,8 +1,8 @@
In add!
x = 10
y = 13
10 + 13 = 23
In sub!
x = 10
y = 13
10 - 13 = -3
In add!
x = 10
y = 13
10 + 13 = 23
In sub!
x = 10
y = 13
10 - 13 = -3

View File

@ -1,17 +1,17 @@
#include <stdio.h>
int
ExportedFromExe ()
{
printf ("This output produced by ExportedFromExe.\n");
return 0;
}
int main()
{
printf ("Hello, world\n");
return 0;
}
#include <stdio.h>
int
ExportedFromExe ()
{
printf ("This output produced by ExportedFromExe.\n");
return 0;
}
int main()
{
printf ("Hello, world\n");
return 0;
}

View File

@ -1,2 +1,2 @@
EXPORTS
ExportedFromExe
EXPORTS
ExportedFromExe

View File

@ -1,40 +1,40 @@
/*
* This version attempts to load dll.dll dynamically, get the address of the
* Add function, and then call it.
*/
#include <stdio.h>
#include <windows.h>
int (*Add)(int x, int y);
int main()
{
HINSTANCE hDll;
int i, j, k;
hDll = LoadLibrary ("dll.dll");
if (!hDll)
{
printf ("Error %d loading dll.\n", GetLastError());
exit (-1);
}
if (!(Add = GetProcAddress (hDll, "Add")))
{
printf ("Error %d getting Add function.\n", GetLastError());
exit (-1);
}
i = 10;
j = 13;
k = Add(i, j);
printf ("i %d, j %d, k %d\n", i, j, k);
FreeLibrary (hDll);
return 0;
}
/*
* This version attempts to load dll.dll dynamically, get the address of the
* Add function, and then call it.
*/
#include <stdio.h>
#include <windows.h>
int (*Add)(int x, int y);
int main()
{
HINSTANCE hDll;
int i, j, k;
hDll = LoadLibrary ("dll.dll");
if (!hDll)
{
printf ("Error %d loading dll.\n", GetLastError());
exit (-1);
}
if (!(Add = GetProcAddress (hDll, "Add")))
{
printf ("Error %d getting Add function.\n", GetLastError());
exit (-1);
}
i = 10;
j = 13;
k = Add(i, j);
printf ("i %d, j %d, k %d\n", i, j, k);
FreeLibrary (hDll);
return 0;
}

View File

@ -1,47 +1,47 @@
/*
* This program attempts to load expexe.exe dynamically, get the address of the
* ExportedFromExe function, and then call it.
*
* This example DOES NOT WORK! I don't know exactly what can be done, but
* it simply seems that LoadLibrary refuses to load executables.
*/
#include <stdio.h>
#include <windows.h>
int (*ExportedFromExe)();
int main()
{
HINSTANCE hDll;
int i, j, k;
hDll = LoadLibrary ("expexe.exe");
if (!hDll)
{
printf ("Error %d loading exe.\n", GetLastError());
exit (-1);
}
if (!(ExportedFromExe = GetProcAddress (hDll, "ExportedFromExe")))
{
printf ("Error %d getting ExportedFromExe function.\n",
GetLastError());
exit (-1);
}
else
{
ExportedFromExe ();
}
/* NOTE: Unlike a DLL the exe doesn't have an entry point which
* initializes global objects and adds __do_global_dtors to
* the atexit list. Thus it should be safe(?) to free the
* library. Of course, this also makes it unsafe to use
* executables at all in this manner.
*/
FreeLibrary (hDll);
return 0;
}
/*
* This program attempts to load expexe.exe dynamically, get the address of the
* ExportedFromExe function, and then call it.
*
* This example DOES NOT WORK! I don't know exactly what can be done, but
* it simply seems that LoadLibrary refuses to load executables.
*/
#include <stdio.h>
#include <windows.h>
int (*ExportedFromExe)();
int main()
{
HINSTANCE hDll;
int i, j, k;
hDll = LoadLibrary ("expexe.exe");
if (!hDll)
{
printf ("Error %d loading exe.\n", GetLastError());
exit (-1);
}
if (!(ExportedFromExe = GetProcAddress (hDll, "ExportedFromExe")))
{
printf ("Error %d getting ExportedFromExe function.\n",
GetLastError());
exit (-1);
}
else
{
ExportedFromExe ();
}
/* NOTE: Unlike a DLL the exe doesn't have an entry point which
* initializes global objects and adds __do_global_dtors to
* the atexit list. Thus it should be safe(?) to free the
* library. Of course, this also makes it unsafe to use
* executables at all in this manner.
*/
FreeLibrary (hDll);
return 0;
}

View File

@ -1,39 +1,39 @@
This directory contains two examples of building DLLs. The exe.c and dll.c
files are used to build a very simple example DLL with a function that
adds two numbers together (and prints some text at the same time). The
exe.c program links to the DLL and prints the results of the function
call.
The C++ example "silly" is more interesting because it involves a DLL which
contains the code for a C++ class. The CSilly class has all of its code in
the sillydll.cpp source file, which is used to build the silly.dll. The
silly.cpp source code builds the main silly.exe executable which makes a
dynamic instance of the object and calls its member functions.
The C++ silly.def file was generated by doing a nm of sillydll.o after it
was generated and then getting the symbol names from that. Removing the
leading underscore produces the appropriate name to include in the EXPORTS
section. Notice there are a few weird functions.
Since there are now several different versions of the GNU compiler capable
of doing this, and they each seem to have different requirements for exports
for classes, it has gotten kind of messy. The silly.def file here is for
use with the native Mingw32 build of the EGCS version of GCC. The silly.def.old
file was the def file I used when I was using Jan-Jaap's Mingw32 native port
of GCC. The Cygnus version is different again, if I recall correctly, but I
don't have it hanging around anymore.
The jamfile builds all the components from the raw sources.
The expected output of exe.exe and silly.exe are in the files exe.exp
and silly.exp.
The source code in this directory is in the PUBLIC DOMAIN and can be
used or abused as you see fit. There is NO WARRANTY for this code,
including (but not limited to) implied warranties of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.
Colin Peters <colin@bird.fu.is.saga-u.ac.jp>
This directory contains two examples of building DLLs. The exe.c and dll.c
files are used to build a very simple example DLL with a function that
adds two numbers together (and prints some text at the same time). The
exe.c program links to the DLL and prints the results of the function
call.
The C++ example "silly" is more interesting because it involves a DLL which
contains the code for a C++ class. The CSilly class has all of its code in
the sillydll.cpp source file, which is used to build the silly.dll. The
silly.cpp source code builds the main silly.exe executable which makes a
dynamic instance of the object and calls its member functions.
The C++ silly.def file was generated by doing a nm of sillydll.o after it
was generated and then getting the symbol names from that. Removing the
leading underscore produces the appropriate name to include in the EXPORTS
section. Notice there are a few weird functions.
Since there are now several different versions of the GNU compiler capable
of doing this, and they each seem to have different requirements for exports
for classes, it has gotten kind of messy. The silly.def file here is for
use with the native Mingw32 build of the EGCS version of GCC. The silly.def.old
file was the def file I used when I was using Jan-Jaap's Mingw32 native port
of GCC. The Cygnus version is different again, if I recall correctly, but I
don't have it hanging around anymore.
The jamfile builds all the components from the raw sources.
The expected output of exe.exe and silly.exe are in the files exe.exp
and silly.exp.
The source code in this directory is in the PUBLIC DOMAIN and can be
used or abused as you see fit. There is NO WARRANTY for this code,
including (but not limited to) implied warranties of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.
Colin Peters <colin@bird.fu.is.saga-u.ac.jp>

View File

@ -1,55 +1,55 @@
//
// C++ test of a dll which contains a C++ class.
//
#include <stdlib.h>
#include <stdio.h>
// Interface of class.
#include "silly.h"
#ifdef DERIVED_TEST
// Here is a derived class too.
class CMoreSilly : public CSilly
{
public:
CMoreSilly (char* szNewName) : CSilly (szNewName) {};
~CMoreSilly ();
WhatsYourName();
};
CMoreSilly::
~CMoreSilly ()
{
printf ("In CMoreSilly \"%s\" destructor!\n", szName);
}
CMoreSilly::
WhatsYourName ()
{
printf ("I'm more silly and my name is \"%s\"\n", szName);
}
#endif
int
main ()
{
CSilly* psilly = new CSilly("silly");
psilly->WhatsYourName();
psilly->Poke(); // Poke him, he should say "Ouch!"
psilly->Stab(4); // Stab him four times he should say "Ugh!!!!"
delete psilly;
#ifdef DERIVED_TEST
psilly = new CMoreSilly("more silly");
psilly->WhatsYourName();
psilly->Stab(5);
delete psilly;
#endif
return 0;
}
//
// C++ test of a dll which contains a C++ class.
//
#include <stdlib.h>
#include <stdio.h>
// Interface of class.
#include "silly.h"
#ifdef DERIVED_TEST
// Here is a derived class too.
class CMoreSilly : public CSilly
{
public:
CMoreSilly (char* szNewName) : CSilly (szNewName) {};
~CMoreSilly ();
WhatsYourName();
};
CMoreSilly::
~CMoreSilly ()
{
printf ("In CMoreSilly \"%s\" destructor!\n", szName);
}
CMoreSilly::
WhatsYourName ()
{
printf ("I'm more silly and my name is \"%s\"\n", szName);
}
#endif
int
main ()
{
CSilly* psilly = new CSilly("silly");
psilly->WhatsYourName();
psilly->Poke(); // Poke him, he should say "Ouch!"
psilly->Stab(4); // Stab him four times he should say "Ugh!!!!"
delete psilly;
#ifdef DERIVED_TEST
psilly = new CMoreSilly("more silly");
psilly->WhatsYourName();
psilly->Stab(5);
delete psilly;
#endif
return 0;
}

View File

@ -1,11 +1,11 @@
EXPORTS
DllMain@12
Poke__6CSilly
Stab__6CSillyi
WhatsYourName__6CSilly
_$_6CSilly
__6CSilly
__6CSillyPc
__tf6CSilly
__ti6CSilly
_vt$6CSilly
EXPORTS
DllMain@12
Poke__6CSilly
Stab__6CSillyi
WhatsYourName__6CSilly
_$_6CSilly
__6CSilly
__6CSillyPc
__tf6CSilly
__ti6CSilly
_vt$6CSilly

View File

@ -1,8 +1,8 @@
I'm silly.
Ouch!
Ugh!!!!
In CSilly destructor.
I'm more silly and my name is "more silly"
Ugh!!!!!
In CMoreSilly "more silly" destructor!
In CSilly destructor.
I'm silly.
Ouch!
Ugh!!!!
In CSilly destructor.
I'm more silly and my name is "more silly"
Ugh!!!!!
In CMoreSilly "more silly" destructor!
In CSilly destructor.

View File

@ -1,27 +1,27 @@
#define DERIVED_TEST 1
class CSilly
{
protected:
char* szName;
public:
CSilly();
CSilly(char* szName);
#ifdef DERIVED_TEST
virtual ~CSilly();
#else
~CSilly();
#endif
Poke ();
Stab (int nTimes);
#ifdef DERIVED_TEST
virtual WhatsYourName ();
#else
WhatsYourName ();
#endif
};
#define DERIVED_TEST 1
class CSilly
{
protected:
char* szName;
public:
CSilly();
CSilly(char* szName);
#ifdef DERIVED_TEST
virtual ~CSilly();
#else
~CSilly();
#endif
Poke ();
Stab (int nTimes);
#ifdef DERIVED_TEST
virtual WhatsYourName ();
#else
WhatsYourName ();
#endif
};

View File

@ -1,107 +1,107 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
#if 0
#define STREAMS_VERSION
#endif
#if defined(STREAMS_VERSION)
#include <iostream.h>
#endif
#include "silly.h"
extern "C"
BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{
return TRUE;
}
CSilly::
CSilly()
{
szName = NULL;
}
CSilly::
CSilly(char* new_szName)
{
szName = new char[strlen(new_szName)+1];
if (szName)
{
strcpy (szName, new_szName);
}
}
CSilly::
~CSilly()
{
printf ("In CSilly destructor.\n");
if (szName)
{
delete szName;
}
}
CSilly::
Poke ()
{
#ifndef STREAMS_VERSION
printf ("Ouch!\n");
#else
cout << "Ouch!" << endl;
#endif
}
CSilly::
Stab (int nTimes)
{
#ifndef STREAMS_VERSION
printf ("Ugh");
#else
cout << "Ugh";
#endif
int i;
for (i = 0; i < nTimes; i++)
{
#ifndef STREAMS_VERSION
putchar('!');
#else
cout << '!' ;
#endif
}
#ifndef STREAMS_VERSION
putchar('\n');
#else
cout << endl;
#endif
}
CSilly::
WhatsYourName ()
{
if (szName)
{
#ifndef STREAMS_VERSION
printf ("I'm %s.\n", szName);
#else
cout << "I'm " << szName << "." << endl;
#endif
}
else
{
#ifndef STREAMS_VERSION
printf ("I have no name.\n");
#else
cout << "I have no name." << endl;
#endif
}
}
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
#if 0
#define STREAMS_VERSION
#endif
#if defined(STREAMS_VERSION)
#include <iostream.h>
#endif
#include "silly.h"
extern "C"
BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{
return TRUE;
}
CSilly::
CSilly()
{
szName = NULL;
}
CSilly::
CSilly(char* new_szName)
{
szName = new char[strlen(new_szName)+1];
if (szName)
{
strcpy (szName, new_szName);
}
}
CSilly::
~CSilly()
{
printf ("In CSilly destructor.\n");
if (szName)
{
delete szName;
}
}
CSilly::
Poke ()
{
#ifndef STREAMS_VERSION
printf ("Ouch!\n");
#else
cout << "Ouch!" << endl;
#endif
}
CSilly::
Stab (int nTimes)
{
#ifndef STREAMS_VERSION
printf ("Ugh");
#else
cout << "Ugh";
#endif
int i;
for (i = 0; i < nTimes; i++)
{
#ifndef STREAMS_VERSION
putchar('!');
#else
cout << '!' ;
#endif
}
#ifndef STREAMS_VERSION
putchar('\n');
#else
cout << endl;
#endif
}
CSilly::
WhatsYourName ()
{
if (szName)
{
#ifndef STREAMS_VERSION
printf ("I'm %s.\n", szName);
#else
cout << "I'm " << szName << "." << endl;
#endif
}
else
{
#ifndef STREAMS_VERSION
printf ("I have no name.\n");
#else
cout << "I have no name." << endl;
#endif
}
}

View File

@ -1,57 +1,57 @@
/*
* An example showing how you can obtain the UNIX-ish file number from a
* FILE* and in turn how you can get the Win32 HANDLE of the file from
* the file number.
*
* This code is in the PUBLIC DOMAIN and has NO WARRANTY.
*
* Colin Peters <colin@fu.is.saga-u.ac.jp>
*/
#include <stdio.h>
#include <io.h>
#include <windows.h>
int
main (int argc, char* argv[])
{
char* szFileName;
FILE* fileIn;
int fnIn;
HANDLE hFileIn;
char caBuf[81];
int nRead;
if (argc >= 2)
{
szFileName = argv[1];
}
else
{
szFileName = "junk.txt";
}
fileIn = fopen (szFileName, "r");
if (!fileIn)
{
printf ("Could not open %s for reading\n", szFileName);
exit(1);
}
fnIn = fileno (fileIn);
hFileIn = (HANDLE) _get_osfhandle (fnIn);
printf ("OS file handle %d\n", (int) hFileIn);
ReadFile (hFileIn, caBuf, 80, &nRead, NULL);
printf ("Read %d bytes using ReadFile.\n", nRead);
caBuf[nRead] = '\0';
printf ("\"%s\"\n", caBuf);
fclose (fileIn);
}
/*
* An example showing how you can obtain the UNIX-ish file number from a
* FILE* and in turn how you can get the Win32 HANDLE of the file from
* the file number.
*
* This code is in the PUBLIC DOMAIN and has NO WARRANTY.
*
* Colin Peters <colin@fu.is.saga-u.ac.jp>
*/
#include <stdio.h>
#include <io.h>
#include <windows.h>
int
main (int argc, char* argv[])
{
char* szFileName;
FILE* fileIn;
int fnIn;
HANDLE hFileIn;
char caBuf[81];
int nRead;
if (argc >= 2)
{
szFileName = argv[1];
}
else
{
szFileName = "junk.txt";
}
fileIn = fopen (szFileName, "r");
if (!fileIn)
{
printf ("Could not open %s for reading\n", szFileName);
exit(1);
}
fnIn = fileno (fileIn);
hFileIn = (HANDLE) _get_osfhandle (fnIn);
printf ("OS file handle %d\n", (int) hFileIn);
ReadFile (hFileIn, caBuf, 80, &nRead, NULL);
printf ("Read %d bytes using ReadFile.\n", nRead);
caBuf[nRead] = '\0';
printf ("\"%s\"\n", caBuf);
fclose (fileIn);
}

View File

@ -1,3 +1,3 @@
Main filehand.exe : filehand.c ;
Main filehand.exe : filehand.c ;

View File

@ -1 +1 @@
This is a test file.
This is a test file.

View File

@ -1,290 +1,290 @@
/*
* fixargv.c
*
* A special function which "fixes" an argv array by replacing arguments
* that need quoting with quoted versions.
*
* NOTE: In order to be reasonably consistent there is some misuse of the
* const keyword here-- which leads to compilation warnings. These
* should be ok to ignore.
*
* This is a sample distributed as part of the Mingw32 package.
*
* Contributors:
* Created by Colin Peters <colin@bird.fu.is.saga-u.ac.jp>
*
* THIS SOFTWARE IS NOT COPYRIGHTED
*
* This source code is offered for use in the public domain. You may
* use, modify or distribute it freely.
*
* This code is distributed in the hope that it will be useful but
* WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY
* DISCLAMED. This includes but is not limited to warrenties of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* $Revision$
* $Author$
* $Date$
*
*/
#include <string.h>
#include "fixargv.h"
/*
* This takes a single string and fixes it, enclosing it in quotes if it
* contains any spaces and/or escaping the quotes it contains.
*/
char*
fix_arg (const char* szArg)
{
int nQuoteAll; /* Does the whole arg need quoting? */
int nBkSlRun; /* How may backslashes in a row? */
char* sz;
char* szNew;
size_t sizeLen;
nQuoteAll = 0;
nBkSlRun = 0;
sz = szArg;
sizeLen = 1;
/* First we figure out how much bigger the new string has to be
* than the old one. */
while (*sz != '\0')
{
/*
* Arguments containing whitespace of wildcards will be
* quoted to preserve tokenization and/or those special
* characters (i.e. wildcarding will NOT be done at the
* other end-- they will get the * and ? characters as is).
* TODO: Is this the best way? Do we want to enable wildcards?
* If so, when?
*/
if (!nQuoteAll &&
(*sz == ' ' || *sz == '\t' || *sz == '*' || *sz == '?'))
{
nQuoteAll = 1;
}
else if (*sz == '\\')
{
nBkSlRun++;
}
else
{
if (*sz == '\"')
{
sizeLen += nBkSlRun + 1;
}
nBkSlRun = 0;
}
sizeLen++;
sz++;
}
if (nQuoteAll)
{
sizeLen += 2;
}
/*
* Make a new string big enough.
*/
szNew = (char*) malloc (sizeLen);
if (!szNew)
{
return NULL;
}
sz = szNew;
/* First enclosing quote for fully quoted args. */
if (nQuoteAll)
{
*sz = '\"';
sz++;
}
/*
* Go through the string putting backslashes in front of quotes,
* and doubling all backslashes immediately in front of quotes.
*/
nBkSlRun = 0;
while (*szArg != '\0')
{
if (*szArg == '\\')
{
nBkSlRun++;
}
else
{
if (*szArg == '\"')
{
while (nBkSlRun > 0)
{
*sz = '\\';
sz++;
nBkSlRun--;
}
*sz = '\\';
sz++;
}
nBkSlRun = 0;
}
*sz = *szArg;
sz++;
szArg++;
}
/* Closing quote for fully quoted args. */
if (nQuoteAll)
{
*sz = '\"';
sz++;
}
*sz = '\0';
return szNew;
}
/*
* Takes argc and argv and returns a new argv with escaped members. Pass
* this fixed argv (along with the old one) to free_fixed_argv after
* you finish with it. Pass in an argc of -1 and make sure the argv vector
* ends with a null pointer to have fix_argv count the arguments for you.
*/
char* const*
fix_argv (int argc, char* const* szaArgv)
{
char** szaNew;
char* sz;
int i;
if (!szaArgv)
{
return NULL;
}
/*
* Count the arguments if asked.
*/
if (argc == -1)
{
for (i = 0; szaArgv[i]; i++)
;
argc = i;
}
/*
* If there are no args or only one arg then do no escaping.
*/
if (argc < 2)
{
return szaArgv;
}
for (i = 1, szaNew = NULL; i < argc; i++)
{
sz = szaArgv[i];
/*
* If an argument needs fixing, then fix it.
*/
if (strpbrk (sz, "\" \t*?"))
{
/*
* If we haven't created a new argv list already
* then make one.
*/
if (!szaNew)
{
szaNew = (char**) malloc ((argc + 1) *
sizeof (char*));
if (!szaNew)
{
return NULL;
}
/*
* Copy previous args from old to new.
*/
memcpy (szaNew, szaArgv, sizeof(char*) * i);
}
/*
* Now do the fixing.
*/
szaNew[i] = fix_arg (sz);
if (!szaNew[i])
{
/* Fixing failed, free up and return error. */
free_fixed_argv (szaNew, szaArgv);
return NULL;
}
}
else if (szaNew)
{
szaNew[i] = sz;
}
}
if (szaNew)
{
/* If we have created a new argv list then we might as well
* terminate it nicely. (And we depend on it in
* free_fixed_argv.) */
szaNew[argc] = NULL;
}
else
{
/* If we didn't create a new argv list then return the
* original. */
return szaArgv;
}
return szaNew;
}
void
free_fixed_argv (char* const* szaFixed, char* const* szaOld)
{
char* const* sza;
/*
* Check for error conditions. Also note that if no corrections
* were required the fixed argv will actually be the same as
* the old one, and we don't need to do anything.
*/
if (!szaFixed || !szaOld || szaFixed == szaOld)
{
return;
}
/*
* Go through all members of the argv list. If any of the
* members in the fixed list are different from the old
* list we free those members.
* NOTE: The first member is never modified, so we don't need to
* check.
*/
sza = szaFixed + 1;
szaOld++;
while (*sza)
{
if (*sza != *szaOld)
{
free (*sza);
}
sza++;
szaOld++;
}
/*
* Now we can free the array of char pointers itself.
*/
free (szaFixed);
}
/*
* fixargv.c
*
* A special function which "fixes" an argv array by replacing arguments
* that need quoting with quoted versions.
*
* NOTE: In order to be reasonably consistent there is some misuse of the
* const keyword here-- which leads to compilation warnings. These
* should be ok to ignore.
*
* This is a sample distributed as part of the Mingw32 package.
*
* Contributors:
* Created by Colin Peters <colin@bird.fu.is.saga-u.ac.jp>
*
* THIS SOFTWARE IS NOT COPYRIGHTED
*
* This source code is offered for use in the public domain. You may
* use, modify or distribute it freely.
*
* This code is distributed in the hope that it will be useful but
* WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY
* DISCLAMED. This includes but is not limited to warrenties of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* $Revision$
* $Author$
* $Date$
*
*/
#include <string.h>
#include "fixargv.h"
/*
* This takes a single string and fixes it, enclosing it in quotes if it
* contains any spaces and/or escaping the quotes it contains.
*/
char*
fix_arg (const char* szArg)
{
int nQuoteAll; /* Does the whole arg need quoting? */
int nBkSlRun; /* How may backslashes in a row? */
char* sz;
char* szNew;
size_t sizeLen;
nQuoteAll = 0;
nBkSlRun = 0;
sz = szArg;
sizeLen = 1;
/* First we figure out how much bigger the new string has to be
* than the old one. */
while (*sz != '\0')
{
/*
* Arguments containing whitespace of wildcards will be
* quoted to preserve tokenization and/or those special
* characters (i.e. wildcarding will NOT be done at the
* other end-- they will get the * and ? characters as is).
* TODO: Is this the best way? Do we want to enable wildcards?
* If so, when?
*/
if (!nQuoteAll &&
(*sz == ' ' || *sz == '\t' || *sz == '*' || *sz == '?'))
{
nQuoteAll = 1;
}
else if (*sz == '\\')
{
nBkSlRun++;
}
else
{
if (*sz == '\"')
{
sizeLen += nBkSlRun + 1;
}
nBkSlRun = 0;
}
sizeLen++;
sz++;
}
if (nQuoteAll)
{
sizeLen += 2;
}
/*
* Make a new string big enough.
*/
szNew = (char*) malloc (sizeLen);
if (!szNew)
{
return NULL;
}
sz = szNew;
/* First enclosing quote for fully quoted args. */
if (nQuoteAll)
{
*sz = '\"';
sz++;
}
/*
* Go through the string putting backslashes in front of quotes,
* and doubling all backslashes immediately in front of quotes.
*/
nBkSlRun = 0;
while (*szArg != '\0')
{
if (*szArg == '\\')
{
nBkSlRun++;
}
else
{
if (*szArg == '\"')
{
while (nBkSlRun > 0)
{
*sz = '\\';
sz++;
nBkSlRun--;
}
*sz = '\\';
sz++;
}
nBkSlRun = 0;
}
*sz = *szArg;
sz++;
szArg++;
}
/* Closing quote for fully quoted args. */
if (nQuoteAll)
{
*sz = '\"';
sz++;
}
*sz = '\0';
return szNew;
}
/*
* Takes argc and argv and returns a new argv with escaped members. Pass
* this fixed argv (along with the old one) to free_fixed_argv after
* you finish with it. Pass in an argc of -1 and make sure the argv vector
* ends with a null pointer to have fix_argv count the arguments for you.
*/
char* const*
fix_argv (int argc, char* const* szaArgv)
{
char** szaNew;
char* sz;
int i;
if (!szaArgv)
{
return NULL;
}
/*
* Count the arguments if asked.
*/
if (argc == -1)
{
for (i = 0; szaArgv[i]; i++)
;
argc = i;
}
/*
* If there are no args or only one arg then do no escaping.
*/
if (argc < 2)
{
return szaArgv;
}
for (i = 1, szaNew = NULL; i < argc; i++)
{
sz = szaArgv[i];
/*
* If an argument needs fixing, then fix it.
*/
if (strpbrk (sz, "\" \t*?"))
{
/*
* If we haven't created a new argv list already
* then make one.
*/
if (!szaNew)
{
szaNew = (char**) malloc ((argc + 1) *
sizeof (char*));
if (!szaNew)
{
return NULL;
}
/*
* Copy previous args from old to new.
*/
memcpy (szaNew, szaArgv, sizeof(char*) * i);
}
/*
* Now do the fixing.
*/
szaNew[i] = fix_arg (sz);
if (!szaNew[i])
{
/* Fixing failed, free up and return error. */
free_fixed_argv (szaNew, szaArgv);
return NULL;
}
}
else if (szaNew)
{
szaNew[i] = sz;
}
}
if (szaNew)
{
/* If we have created a new argv list then we might as well
* terminate it nicely. (And we depend on it in
* free_fixed_argv.) */
szaNew[argc] = NULL;
}
else
{
/* If we didn't create a new argv list then return the
* original. */
return szaArgv;
}
return szaNew;
}
void
free_fixed_argv (char* const* szaFixed, char* const* szaOld)
{
char* const* sza;
/*
* Check for error conditions. Also note that if no corrections
* were required the fixed argv will actually be the same as
* the old one, and we don't need to do anything.
*/
if (!szaFixed || !szaOld || szaFixed == szaOld)
{
return;
}
/*
* Go through all members of the argv list. If any of the
* members in the fixed list are different from the old
* list we free those members.
* NOTE: The first member is never modified, so we don't need to
* check.
*/
sza = szaFixed + 1;
szaOld++;
while (*sza)
{
if (*sza != *szaOld)
{
free (*sza);
}
sza++;
szaOld++;
}
/*
* Now we can free the array of char pointers itself.
*/
free (szaFixed);
}

View File

@ -1,24 +1,24 @@
/*
* fixargv.h
*
* Prototypes of utility functions for 'properly' escaping argv vectors.
*
* THIS SOFTWARE IS NOT COPYRIGHTED
*
* This source code is offered for use in the public domain. You may
* use, modify or distribute it freely.
*
* $Revision$
* $Author$
* $Date$
*
*/
#ifndef _FIXARGV_H_
#define _FIXARGV_H_
char* fix_arg (const char* szArg);
char* const* fix_argv (int argc, char* const* szaArgv);
void free_fixed_argv (char* const* szaFixed, char* const* szaOld);
#endif
/*
* fixargv.h
*
* Prototypes of utility functions for 'properly' escaping argv vectors.
*
* THIS SOFTWARE IS NOT COPYRIGHTED
*
* This source code is offered for use in the public domain. You may
* use, modify or distribute it freely.
*
* $Revision$
* $Author$
* $Date$
*
*/
#ifndef _FIXARGV_H_
#define _FIXARGV_H_
char* fix_arg (const char* szArg);
char* const* fix_argv (int argc, char* const* szaArgv);
void free_fixed_argv (char* const* szaFixed, char* const* szaOld);
#endif

View File

@ -1,85 +1,85 @@
This code is a utility function I was considering adding to Mingw32. The
Microsoft versions of argc, argv construction use quotes and backslashes
to allow the user to pass arguments containing spaces (or quotes) to
programs they invoke. The rules are
- Arguments containing spaces must be enclosed in quotes.
- A quote can be passed by preceeding it with a backslash.
- Backslashes immediately preceeding a quote must be doubled to avoid
escaping the quote.
Thus an argument like:
-D="Foo Bar\\"
needs to be mangled as:
"-D\"Foo Bar\\\\\""
in order to get to the program as what was intended above.
The fix_argv set of functions is meant to be used with spawnv and the
like to allow a program to set up an argv array for the spawned program
and have that array duplicated *exactly* in the spawned program, no
matter what it contains (it also quotes 'globbing' characters like *
and ?, so it does not matter if the destination has globbing turned on
or not; it might be a reasonable extension to allow a flag to allow
globbing characters to pass through unmolested, but they would still
be quoted if the string contained whitespace).
The reason for writing this came up because of problems with arguments
like -DBLAH="Foo Bar" to GCC (define BLAH as a preprocessor constant
being the string "Foo Bar", including the quotes). Because GCC simply
passes the argument directly to CPP (the preprocessor) it had to be
escaped *twice*:
"-DBLAH=\"\\\"Foo Bar\\\"\""
This would reach GCC as
-DBLAH="\"Foo Bar\""
And that would reach CPP as the desired
-DBLAH="Foo Bar"
One level of quoting and escaping is to be expected (although MS's
standard is, arguably, not very good), but forcing the user to know
how many different programs the argument is going to pass through,
and perform double quoting and escaping, seems unreasonable. If
GCC and friends all used fix_argv (they use their own version of
it now) then the original argument could be
"-DBLAH=\"Foo Bar\""
And that would work fine, no matter how many different tools it
passed through.
The only basic limitation with this code is that it assumes that all
the spawned programs use Microsoft-type escaping when interpreting
their command line. Most programs on Win32 machines do (anything
compiled with Mingw32 will).
For now, this code has been relegated to 'sample' status. If you want
to use it, feel free (it is public domain after all).
Colin.
P.S. Just out of interest you might try writing your own little program
to look at the interaction of wildcards and quotes. Use the glob.exe
program in ../globbing and see what it does with
glob "foo*.txt"
even if there are files foo.txt and foobar.txt in the same directory.
Note that
del "My *.txt"
works (i.e. it deletes all files starting with My<space>). This could
not be done unless del does globbing *after* processing escapes and
quotes, which is not the way it seems to work normally (again see
the glob example).
This code is a utility function I was considering adding to Mingw32. The
Microsoft versions of argc, argv construction use quotes and backslashes
to allow the user to pass arguments containing spaces (or quotes) to
programs they invoke. The rules are
- Arguments containing spaces must be enclosed in quotes.
- A quote can be passed by preceeding it with a backslash.
- Backslashes immediately preceeding a quote must be doubled to avoid
escaping the quote.
Thus an argument like:
-D="Foo Bar\\"
needs to be mangled as:
"-D\"Foo Bar\\\\\""
in order to get to the program as what was intended above.
The fix_argv set of functions is meant to be used with spawnv and the
like to allow a program to set up an argv array for the spawned program
and have that array duplicated *exactly* in the spawned program, no
matter what it contains (it also quotes 'globbing' characters like *
and ?, so it does not matter if the destination has globbing turned on
or not; it might be a reasonable extension to allow a flag to allow
globbing characters to pass through unmolested, but they would still
be quoted if the string contained whitespace).
The reason for writing this came up because of problems with arguments
like -DBLAH="Foo Bar" to GCC (define BLAH as a preprocessor constant
being the string "Foo Bar", including the quotes). Because GCC simply
passes the argument directly to CPP (the preprocessor) it had to be
escaped *twice*:
"-DBLAH=\"\\\"Foo Bar\\\"\""
This would reach GCC as
-DBLAH="\"Foo Bar\""
And that would reach CPP as the desired
-DBLAH="Foo Bar"
One level of quoting and escaping is to be expected (although MS's
standard is, arguably, not very good), but forcing the user to know
how many different programs the argument is going to pass through,
and perform double quoting and escaping, seems unreasonable. If
GCC and friends all used fix_argv (they use their own version of
it now) then the original argument could be
"-DBLAH=\"Foo Bar\""
And that would work fine, no matter how many different tools it
passed through.
The only basic limitation with this code is that it assumes that all
the spawned programs use Microsoft-type escaping when interpreting
their command line. Most programs on Win32 machines do (anything
compiled with Mingw32 will).
For now, this code has been relegated to 'sample' status. If you want
to use it, feel free (it is public domain after all).
Colin.
P.S. Just out of interest you might try writing your own little program
to look at the interaction of wildcards and quotes. Use the glob.exe
program in ../globbing and see what it does with
glob "foo*.txt"
even if there are files foo.txt and foobar.txt in the same directory.
Note that
del "My *.txt"
works (i.e. it deletes all files starting with My<space>). This could
not be done unless del does globbing *after* processing escapes and
quotes, which is not the way it seems to work normally (again see
the glob example).

View File

@ -1,46 +1,46 @@
/*
* A sample program demonstrating how to use _CRT_fmode to change the default
* file opening mode to binary AND change stdin, stdout and stderr. Redirect
* stdout to a file from the command line to see the difference.
*
* Also try directing a file into stdin. If you type into stdin you will get
* \r\n at the end of every line... unlike UNIX. But at least if you
* redirect a file in you will get exactly the characters in the file as input.
*
* THIS CODE IS IN THE PUBLIC DOMAIN.
*
* Colin Peters <colin@fu.is.saga-u.ac.jp>
*/
#include <stdio.h>
#include <fcntl.h>
unsigned int _CRT_fmode = _O_BINARY;
main ()
{
char* sz = "This is line one.\nThis is line two.\n";
FILE* fp;
int c;
printf (sz);
/* Note how this fopen does NOT indicate "wb" to open the file in
* binary mode. */
fp = fopen ("all.out", "w");
fprintf (fp, sz);
fclose (fp);
if (_isatty (_fileno(stdin)))
{
fprintf (stderr, "Waiting for input, press Ctrl-Z to finish.\n");
}
while ((c = fgetc(stdin)) != EOF)
{
printf ("\'%c\' %02X\n", (char) c, c);
}
}
/*
* A sample program demonstrating how to use _CRT_fmode to change the default
* file opening mode to binary AND change stdin, stdout and stderr. Redirect
* stdout to a file from the command line to see the difference.
*
* Also try directing a file into stdin. If you type into stdin you will get
* \r\n at the end of every line... unlike UNIX. But at least if you
* redirect a file in you will get exactly the characters in the file as input.
*
* THIS CODE IS IN THE PUBLIC DOMAIN.
*
* Colin Peters <colin@fu.is.saga-u.ac.jp>
*/
#include <stdio.h>
#include <fcntl.h>
unsigned int _CRT_fmode = _O_BINARY;
main ()
{
char* sz = "This is line one.\nThis is line two.\n";
FILE* fp;
int c;
printf (sz);
/* Note how this fopen does NOT indicate "wb" to open the file in
* binary mode. */
fp = fopen ("all.out", "w");
fprintf (fp, sz);
fclose (fp);
if (_isatty (_fileno(stdin)))
{
fprintf (stderr, "Waiting for input, press Ctrl-Z to finish.\n");
}
while ((c = fgetc(stdin)) != EOF)
{
printf ("\'%c\' %02X\n", (char) c, c);
}
}

View File

@ -1,5 +1,5 @@
Main test.exe : test.c ;
Main all.exe : all.c ;
Main test.exe : test.c ;
Main all.exe : all.c ;

View File

@ -1,5 +1,5 @@
These two demos show how _fmode and _CRT_fmode can be used to modify the
default file opening mode (text vs. binary) and/or the mode of the standard
file handles.
These two demos show how _fmode and _CRT_fmode can be used to modify the
default file opening mode (text vs. binary) and/or the mode of the standard
file handles.

View File

@ -1,31 +1,31 @@
/*
* A sample program demonstrating how to use fmode to change the default
* file opening mode to binary. NOTE: Does not change stdin, stdout or
* stderr.
*
* THIS CODE IS IN THE PUBLIC DOMAIN.
*
* Colin Peters <colin@fu.is.saga-u.ac.jp>
*/
#include <stdio.h>
#include <fcntl.h> /* Required to get _fmode and _O_BINARY */
main ()
{
char* sz = "This is line one.\nThis is line two.\n";
FILE* fp;
_fmode = _O_BINARY;
printf (sz);
/* Note how this fopen does NOT indicate "wb" to open the file in
* binary mode. */
fp = fopen ("test.out", "w");
fprintf (fp, sz);
fclose (fp);
}
/*
* A sample program demonstrating how to use fmode to change the default
* file opening mode to binary. NOTE: Does not change stdin, stdout or
* stderr.
*
* THIS CODE IS IN THE PUBLIC DOMAIN.
*
* Colin Peters <colin@fu.is.saga-u.ac.jp>
*/
#include <stdio.h>
#include <fcntl.h> /* Required to get _fmode and _O_BINARY */
main ()
{
char* sz = "This is line one.\nThis is line two.\n";
FILE* fp;
_fmode = _O_BINARY;
printf (sz);
/* Note how this fopen does NOT indicate "wb" to open the file in
* binary mode. */
fp = fopen ("test.out", "w");
fprintf (fp, sz);
fclose (fp);
}

View File

@ -1,9 +1,9 @@
#
# A simple example which prints a message on a selected printer. This won't
# work right unless you make PRINTDLG a packed structure!
#
Main prntest.exe : prntest.c ;
Gui prntest.exe ;
#
# A simple example which prints a message on a selected printer. This won't
# work right unless you make PRINTDLG a packed structure!
#
Main prntest.exe : prntest.c ;
Gui prntest.exe ;

View File

@ -1,65 +1,65 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
main ()
{
PRINTDLG pd;
DOCINFO di;
char* szMessage;
memset (&pd, 0, sizeof(PRINTDLG));
memset (&di, 0, sizeof(DOCINFO));
di.cbSize = sizeof(DOCINFO);
di.lpszDocName = "Test";
pd.lStructSize = sizeof(PRINTDLG);
pd.Flags = PD_PAGENUMS | PD_RETURNDC;
pd.nFromPage = 1;
pd.nToPage = 1;
pd.nMinPage = 1;
pd.nMaxPage = 1;
szMessage = 0;
if (PrintDlg (&pd))
{
if (pd.hDC)
{
if (StartDoc (pd.hDC, &di) != SP_ERROR)
{
StartPage (pd.hDC);
TextOut (pd.hDC, 0, 0, "Hello, printer!", 15);
EndPage (pd.hDC);
EndDoc (pd.hDC);
szMessage = "Printed.";
}
else
{
szMessage = "Could not start document.";
}
}
else
{
szMessage = "Could not create device context.";
}
}
else
{
szMessage = "Canceled or printer could not be setup.";
}
if (szMessage)
{
MessageBox (NULL, szMessage, "Print Test", MB_OK);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
main ()
{
PRINTDLG pd;
DOCINFO di;
char* szMessage;
memset (&pd, 0, sizeof(PRINTDLG));
memset (&di, 0, sizeof(DOCINFO));
di.cbSize = sizeof(DOCINFO);
di.lpszDocName = "Test";
pd.lStructSize = sizeof(PRINTDLG);
pd.Flags = PD_PAGENUMS | PD_RETURNDC;
pd.nFromPage = 1;
pd.nToPage = 1;
pd.nMinPage = 1;
pd.nMaxPage = 1;
szMessage = 0;
if (PrintDlg (&pd))
{
if (pd.hDC)
{
if (StartDoc (pd.hDC, &di) != SP_ERROR)
{
StartPage (pd.hDC);
TextOut (pd.hDC, 0, 0, "Hello, printer!", 15);
EndPage (pd.hDC);
EndDoc (pd.hDC);
szMessage = "Printed.";
}
else
{
szMessage = "Could not start document.";
}
}
else
{
szMessage = "Could not create device context.";
}
}
else
{
szMessage = "Canceled or printer could not be setup.";
}
if (szMessage)
{
MessageBox (NULL, szMessage, "Print Test", MB_OK);
}
return 0;
}

View File

@ -1,112 +1,112 @@
int
__except_handler3(
struct _EXCEPTION_RECORD* pExceptionRecord,
struct EXCEPTION_REGISTRATION* pRegistrationFrame,
struct _CONTEXT* pContextRecord,
void* pDispatcherContext
)
{
LONG filterFuncRet;
LONG trylevel;
EXCEPTION_POINTERS exceptPtrs;
PSCOPETABLE pScopeTable;
CLD // Clear the direction flag (make no assumptions!)
// if neither the EXCEPTION_UNWINDING nor EXCEPTION_EXIT_UNWIND bit
// is set... This is true the first time through the handler (the
// non-unwinding case)
if ( ! (pExceptionRecord->ExceptionFlags
& (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND)
) )
{
// Build the EXCEPTION_POINTERS structure on the stack
exceptPtrs.ExceptionRecord = pExceptionRecord;
exceptPtrs.ContextRecord = pContextRecord;
// Put the pointer to the EXCEPTION_POINTERS 4 bytes below the
// establisher frame. See ASM code for GetExceptionInformation
*(PDWORD)((PBYTE)pRegistrationFrame - 4) = &exceptPtrs;
// Get initial "trylevel" value
trylevel = pRegistrationFrame->trylevel
// Get a pointer to the scopetable array
scopeTable = pRegistrationFrame->scopetable;
search_for_handler:
if ( pRegistrationFrame->trylevel != TRYLEVEL_NONE )
{
if ( pRegistrationFrame->scopetable[trylevel].lpfnFilter )
{
PUSH EBP // Save this frame EBP
// !!!Very Important!!! Switch to original EBP. This is
// what allows all locals in the frame to have the same
// value as before the exception occurred.
EBP = &pRegistrationFrame->_ebp
// Call the filter function
filterFuncRet = scopetable[trylevel].lpfnFilter();
POP EBP // Restore handler frame EBP
if ( filterFuncRet != EXCEPTION_CONTINUE_SEARCH )
{
if ( filterFuncRet < 0 ) // EXCEPTION_CONTINUE_EXECUTION
return ExceptionContinueExecution;
// If we get here, EXCEPTION_EXECUTE_HANDLER was specified
scopetable == pRegistrationFrame->scopetable
// Does the actual OS cleanup of registration frames
// Causes this function to recurse
__global_unwind2( pRegistrationFrame );
// Once we get here, everything is all cleaned up, except
// for the last frame, where we'll continue execution
EBP = &pRegistrationFrame->_ebp
__local_unwind2( pRegistrationFrame, trylevel );
// NLG == "non-local-goto" (setjmp/longjmp stuff)
__NLG_Notify( 1 ); // EAX == scopetable->lpfnHandler
// Set the current trylevel to whatever SCOPETABLE entry
// was being used when a handler was found
pRegistrationFrame->trylevel = scopetable->previousTryLevel;
// Call the _except {} block. Never returns.
pRegistrationFrame->scopetable[trylevel].lpfnHandler();
}
}
scopeTable = pRegistrationFrame->scopetable;
trylevel = scopeTable->previousTryLevel
goto search_for_handler;
}
else // trylevel == TRYLEVEL_NONE
{
retvalue == DISPOSITION_CONTINUE_SEARCH;
}
}
else // EXCEPTION_UNWINDING or EXCEPTION_EXIT_UNWIND flags are set
{
PUSH EBP // Save EBP
EBP = pRegistrationFrame->_ebp // Set EBP for __local_unwind2
__local_unwind2( pRegistrationFrame, TRYLEVEL_NONE )
POP EBP // Restore EBP
retvalue == DISPOSITION_CONTINUE_SEARCH;
}
}
int
__except_handler3(
struct _EXCEPTION_RECORD* pExceptionRecord,
struct EXCEPTION_REGISTRATION* pRegistrationFrame,
struct _CONTEXT* pContextRecord,
void* pDispatcherContext
)
{
LONG filterFuncRet;
LONG trylevel;
EXCEPTION_POINTERS exceptPtrs;
PSCOPETABLE pScopeTable;
CLD // Clear the direction flag (make no assumptions!)
// if neither the EXCEPTION_UNWINDING nor EXCEPTION_EXIT_UNWIND bit
// is set... This is true the first time through the handler (the
// non-unwinding case)
if ( ! (pExceptionRecord->ExceptionFlags
& (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND)
) )
{
// Build the EXCEPTION_POINTERS structure on the stack
exceptPtrs.ExceptionRecord = pExceptionRecord;
exceptPtrs.ContextRecord = pContextRecord;
// Put the pointer to the EXCEPTION_POINTERS 4 bytes below the
// establisher frame. See ASM code for GetExceptionInformation
*(PDWORD)((PBYTE)pRegistrationFrame - 4) = &exceptPtrs;
// Get initial "trylevel" value
trylevel = pRegistrationFrame->trylevel
// Get a pointer to the scopetable array
scopeTable = pRegistrationFrame->scopetable;
search_for_handler:
if ( pRegistrationFrame->trylevel != TRYLEVEL_NONE )
{
if ( pRegistrationFrame->scopetable[trylevel].lpfnFilter )
{
PUSH EBP // Save this frame EBP
// !!!Very Important!!! Switch to original EBP. This is
// what allows all locals in the frame to have the same
// value as before the exception occurred.
EBP = &pRegistrationFrame->_ebp
// Call the filter function
filterFuncRet = scopetable[trylevel].lpfnFilter();
POP EBP // Restore handler frame EBP
if ( filterFuncRet != EXCEPTION_CONTINUE_SEARCH )
{
if ( filterFuncRet < 0 ) // EXCEPTION_CONTINUE_EXECUTION
return ExceptionContinueExecution;
// If we get here, EXCEPTION_EXECUTE_HANDLER was specified
scopetable == pRegistrationFrame->scopetable
// Does the actual OS cleanup of registration frames
// Causes this function to recurse
__global_unwind2( pRegistrationFrame );
// Once we get here, everything is all cleaned up, except
// for the last frame, where we'll continue execution
EBP = &pRegistrationFrame->_ebp
__local_unwind2( pRegistrationFrame, trylevel );
// NLG == "non-local-goto" (setjmp/longjmp stuff)
__NLG_Notify( 1 ); // EAX == scopetable->lpfnHandler
// Set the current trylevel to whatever SCOPETABLE entry
// was being used when a handler was found
pRegistrationFrame->trylevel = scopetable->previousTryLevel;
// Call the _except {} block. Never returns.
pRegistrationFrame->scopetable[trylevel].lpfnHandler();
}
}
scopeTable = pRegistrationFrame->scopetable;
trylevel = scopeTable->previousTryLevel
goto search_for_handler;
}
else // trylevel == TRYLEVEL_NONE
{
retvalue == DISPOSITION_CONTINUE_SEARCH;
}
}
else // EXCEPTION_UNWINDING or EXCEPTION_EXIT_UNWIND flags are set
{
PUSH EBP // Save EBP
EBP = pRegistrationFrame->_ebp // Set EBP for __local_unwind2
__local_unwind2( pRegistrationFrame, TRYLEVEL_NONE )
POP EBP // Restore EBP
retvalue == DISPOSITION_CONTINUE_SEARCH;
}
}

View File

@ -1,68 +1,68 @@
#include <stdlib.h>
#include <stdio.h>
#include <excpt.h>
#include <windows.h>
#include "exutil.h"
void
WalkExceptionHandlers ()
{
PEXCEPTION_REGISTRATION_RECORD p;
int i;
__asm__("movl %%fs:0,%%eax;movl %%eax,%0" : "=g" (p) : : "%eax");
i = 0;
while (p != (PEXCEPTION_REGISTRATION_RECORD) -1 && p)
{
printf ("Registration %d at %08x : ", i, p);
printf ("Handler = %08x ", p->handler);
printf ("Next Registration = %08x\n", p->prev);
p = p->prev;
i++;
}
printf ("End of exception handler list.\n");
fflush (stdout);
}
void
DumpExceptionRecord (struct _EXCEPTION_RECORD* pExRec)
{
printf ("Exception: Code = %08x Flags %08x", pExRec->ExceptionCode,
pExRec->ExceptionFlags);
if (pExRec->ExceptionFlags)
{
printf (" ( ");
if (pExRec->ExceptionFlags & EH_NONCONTINUABLE)
{
printf ("EH_NONCONTINUABLE ");
}
if (pExRec->ExceptionFlags & EH_UNWINDING)
{
printf ("EH_UNWINDING ");
}
if (pExRec->ExceptionFlags & EH_EXIT_UNWIND)
{
printf ("EH_EXIT_UNWIND ");
}
if (pExRec->ExceptionFlags & EH_STACK_INVALID)
{
printf ("EH_STACK_INVALID ");
}
if (pExRec->ExceptionFlags & EH_NESTED_CALL)
{
printf ("EH_NESTED_CALL ");
}
printf (")\n");
}
else
{
printf ("\n");
}
fflush(stdout);
}
#include <stdlib.h>
#include <stdio.h>
#include <excpt.h>
#include <windows.h>
#include "exutil.h"
void
WalkExceptionHandlers ()
{
PEXCEPTION_REGISTRATION_RECORD p;
int i;
__asm__("movl %%fs:0,%%eax;movl %%eax,%0" : "=g" (p) : : "%eax");
i = 0;
while (p != (PEXCEPTION_REGISTRATION_RECORD) -1 && p)
{
printf ("Registration %d at %08x : ", i, p);
printf ("Handler = %08x ", p->handler);
printf ("Next Registration = %08x\n", p->prev);
p = p->prev;
i++;
}
printf ("End of exception handler list.\n");
fflush (stdout);
}
void
DumpExceptionRecord (struct _EXCEPTION_RECORD* pExRec)
{
printf ("Exception: Code = %08x Flags %08x", pExRec->ExceptionCode,
pExRec->ExceptionFlags);
if (pExRec->ExceptionFlags)
{
printf (" ( ");
if (pExRec->ExceptionFlags & EH_NONCONTINUABLE)
{
printf ("EH_NONCONTINUABLE ");
}
if (pExRec->ExceptionFlags & EH_UNWINDING)
{
printf ("EH_UNWINDING ");
}
if (pExRec->ExceptionFlags & EH_EXIT_UNWIND)
{
printf ("EH_EXIT_UNWIND ");
}
if (pExRec->ExceptionFlags & EH_STACK_INVALID)
{
printf ("EH_STACK_INVALID ");
}
if (pExRec->ExceptionFlags & EH_NESTED_CALL)
{
printf ("EH_NESTED_CALL ");
}
printf (")\n");
}
else
{
printf ("\n");
}
fflush(stdout);
}

View File

@ -1,3 +1,3 @@
EXPORTS
WalkExceptionHandlers
DumpExceptionRecord
EXPORTS
WalkExceptionHandlers
DumpExceptionRecord

View File

@ -1,23 +1,23 @@
/*
* Definitions of some internal stuff for exception handling, including
* a version of the all-important EXCEPTION_REGISTRATION_RECORD.
*/
#ifndef _EXUTIL_H_
#define _EXUTIL_H_
#include <windows.h>
#include <excpt.h>
#ifdef __cplusplus
extern "C" {
#endif
void WalkExceptionHandlers ();
void DumpExceptionRecord (struct _EXCEPTION_RECORD* pExRec);
#ifdef __cplusplus
}
#endif
#endif
/*
* Definitions of some internal stuff for exception handling, including
* a version of the all-important EXCEPTION_REGISTRATION_RECORD.
*/
#ifndef _EXUTIL_H_
#define _EXUTIL_H_
#include <windows.h>
#include <excpt.h>
#ifdef __cplusplus
extern "C" {
#endif
void WalkExceptionHandlers ();
void DumpExceptionRecord (struct _EXCEPTION_RECORD* pExRec);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,13 +1,13 @@
Dll exutil.dll : exutil.c ;
ImportLib libexutil.a : exutil.def ;
Main sehtest.exe : sehtest.c ;
Main sehfix.exe : sehfix.c ;
Main sehsub.exe : sehsub.c ;
LinkLibraries sehtest.exe sehfix.exe sehsub.exe : libexutil.a ;
Dll exutil.dll : exutil.c ;
ImportLib libexutil.a : exutil.def ;
Main sehtest.exe : sehtest.c ;
Main sehfix.exe : sehfix.c ;
Main sehsub.exe : sehsub.c ;
LinkLibraries sehtest.exe sehfix.exe sehsub.exe : libexutil.a ;

View File

@ -1,60 +1,60 @@
/*
* sehfix.c
*
* A test program involving an exception handler that fixes the exception
* causing condition.
*
* In this code we install an exception handler my_handler and then a piece
* of inline assembly attempts to write at the address marked in eax, after
* setting eax to 10. This should produce an exception. The handler then
* changes the eax register of the exception context to be the address of
* a static variable and restarts the code. This should allow everything
* to continue.
*/
#include <windows.h>
#include <excpt.h>
#include "exutil.h"
int x;
EXCEPTION_DISPOSITION
my_handler (
struct _EXCEPTION_RECORD* pExceptionRec,
void* pEstablisherFrame,
struct _CONTEXT* pContextRecord,
void* pDispatcherContext
)
{
printf ("In my exception handler!\n");
DumpExceptionRecord (pExceptionRec);
pContextRecord->Eax = (DWORD) &x;
return ExceptionContinueExecution;
}
main ()
{
x = 2;
printf ("x = %d\n", x);
WalkExceptionHandlers();
__try1(my_handler)
WalkExceptionHandlers();
/* This assembly code should produce an exception. */
__asm__("movl $10,%%eax;movl $1,(%%eax);" : : : "%eax");
__except1
WalkExceptionHandlers();
printf ("x = %d\n", x);
printf ("Finished!\n");
}
/*
* sehfix.c
*
* A test program involving an exception handler that fixes the exception
* causing condition.
*
* In this code we install an exception handler my_handler and then a piece
* of inline assembly attempts to write at the address marked in eax, after
* setting eax to 10. This should produce an exception. The handler then
* changes the eax register of the exception context to be the address of
* a static variable and restarts the code. This should allow everything
* to continue.
*/
#include <windows.h>
#include <excpt.h>
#include "exutil.h"
int x;
EXCEPTION_DISPOSITION
my_handler (
struct _EXCEPTION_RECORD* pExceptionRec,
void* pEstablisherFrame,
struct _CONTEXT* pContextRecord,
void* pDispatcherContext
)
{
printf ("In my exception handler!\n");
DumpExceptionRecord (pExceptionRec);
pContextRecord->Eax = (DWORD) &x;
return ExceptionContinueExecution;
}
main ()
{
x = 2;
printf ("x = %d\n", x);
WalkExceptionHandlers();
__try1(my_handler)
WalkExceptionHandlers();
/* This assembly code should produce an exception. */
__asm__("movl $10,%%eax;movl $1,(%%eax);" : : : "%eax");
__except1
WalkExceptionHandlers();
printf ("x = %d\n", x);
printf ("Finished!\n");
}

View File

@ -1,43 +1,43 @@
/*
* sehsub.c
*
* In an attempt to see what might be going on inside CRTDLL, this program
* walks the exception list after creating a new thread with _beginthread.
*
* It turns out that _beginthread DOES install an exception handler, as
* expected, but this handler is NOT exported by CRTDLL (it is certainly
* not _except_handler2 or _XcptFilter)... an odd and unpleasant turn of
* events.
*/
#include <windows.h>
#include <excpt.h>
#include <process.h>
#include "exutil.h"
extern void* __imp__except_handler3;
unsigned
my_thread (void * p)
{
printf ("In my thread.\n");
WalkExceptionHandlers();
return 0;
}
main ()
{
unsigned long h;
unsigned id;
printf ("In main.\n");
WalkExceptionHandlers();
printf ("Except_handler3 %08x\n", __imp__except_handler3);
h = _beginthreadex (NULL, 0, my_thread, NULL, 0, &id);
WaitForSingleObject ((HANDLE) h, INFINITE);
CloseHandle ((HANDLE) h);
return;
}
/*
* sehsub.c
*
* In an attempt to see what might be going on inside CRTDLL, this program
* walks the exception list after creating a new thread with _beginthread.
*
* It turns out that _beginthread DOES install an exception handler, as
* expected, but this handler is NOT exported by CRTDLL (it is certainly
* not _except_handler2 or _XcptFilter)... an odd and unpleasant turn of
* events.
*/
#include <windows.h>
#include <excpt.h>
#include <process.h>
#include "exutil.h"
extern void* __imp__except_handler3;
unsigned
my_thread (void * p)
{
printf ("In my thread.\n");
WalkExceptionHandlers();
return 0;
}
main ()
{
unsigned long h;
unsigned id;
printf ("In main.\n");
WalkExceptionHandlers();
printf ("Except_handler3 %08x\n", __imp__except_handler3);
h = _beginthreadex (NULL, 0, my_thread, NULL, 0, &id);
WaitForSingleObject ((HANDLE) h, INFINITE);
CloseHandle ((HANDLE) h);
return;
}

View File

@ -1,72 +1,72 @@
/*
* This file tests some of the basics of structured exception handling as
* implemented in excpt.h and the Windows API header files.
*
* The program installs two exception handlers, then attempts to write to
* a pointer to an invalid address. This causes an exception which passes
* through the exception handlers and on to the default system exception
* handler. That handler brings up the dialog box all Windows users know
* and love, and then the program is terminated.
*
* You might note that after the initial run up through our exception frames
* we get a second run up through them with the exception code
* STATUS_INVALID_DISPOSITION and the code EH_UNWINDING. This seems normal
* except that the code got changed from the previous STATUS_ACCESS_VIOLATION.
* I don't understand that bit particularly.
*/
#include <stdio.h>
#include <excpt.h>
#include "exutil.h"
EXCEPTION_DISPOSITION
my_handler (
struct _EXCEPTION_RECORD* pExceptionRec,
void* pEstablisherFrame,
struct _CONTEXT* pContextRecord,
void* pDispatcherContext
)
{
printf ("In my exception handler!\n");
DumpExceptionRecord (pExceptionRec);
return ExceptionContinueSearch;
}
EXCEPTION_DISPOSITION
my_handler2 (
struct _EXCEPTION_RECORD* pExceptionRec,
void* pEstablisherFrame,
struct _CONTEXT* pContextRecord,
void* pDispatcherContext
)
{
printf ("In top exception handler!\n");
DumpExceptionRecord (pExceptionRec);
return ExceptionContinueSearch;
}
main ()
{
char* x;
printf ("my_handler2 = %08x\n", my_handler2);
printf ("my_handler = %08x\n", my_handler);
WalkExceptionHandlers();
__try1(my_handler2)
x = (char*) 10;
WalkExceptionHandlers();
__try1(my_handler)
WalkExceptionHandlers();
*x = 1;
__except1
__except1
printf ("Finished!\n");
}
/*
* This file tests some of the basics of structured exception handling as
* implemented in excpt.h and the Windows API header files.
*
* The program installs two exception handlers, then attempts to write to
* a pointer to an invalid address. This causes an exception which passes
* through the exception handlers and on to the default system exception
* handler. That handler brings up the dialog box all Windows users know
* and love, and then the program is terminated.
*
* You might note that after the initial run up through our exception frames
* we get a second run up through them with the exception code
* STATUS_INVALID_DISPOSITION and the code EH_UNWINDING. This seems normal
* except that the code got changed from the previous STATUS_ACCESS_VIOLATION.
* I don't understand that bit particularly.
*/
#include <stdio.h>
#include <excpt.h>
#include "exutil.h"
EXCEPTION_DISPOSITION
my_handler (
struct _EXCEPTION_RECORD* pExceptionRec,
void* pEstablisherFrame,
struct _CONTEXT* pContextRecord,
void* pDispatcherContext
)
{
printf ("In my exception handler!\n");
DumpExceptionRecord (pExceptionRec);
return ExceptionContinueSearch;
}
EXCEPTION_DISPOSITION
my_handler2 (
struct _EXCEPTION_RECORD* pExceptionRec,
void* pEstablisherFrame,
struct _CONTEXT* pContextRecord,
void* pDispatcherContext
)
{
printf ("In top exception handler!\n");
DumpExceptionRecord (pExceptionRec);
return ExceptionContinueSearch;
}
main ()
{
char* x;
printf ("my_handler2 = %08x\n", my_handler2);
printf ("my_handler = %08x\n", my_handler);
WalkExceptionHandlers();
__try1(my_handler2)
x = (char*) 10;
WalkExceptionHandlers();
__try1(my_handler)
WalkExceptionHandlers();
*x = 1;
__except1
__except1
printf ("Finished!\n");
}

View File

@ -1,33 +1,33 @@
#include <windows.h>
BOOL WINAPI
DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
printf ("DLL Attached.\n");
break;
case DLL_PROCESS_DETACH:
printf ("DLL Detached.\n");
break;
case DLL_THREAD_ATTACH:
printf ("DLL Thread Attached.\n");
break;
case DLL_THREAD_DETACH:
printf ("DLL Thread Detached.\n");
break;
}
return TRUE;
}
void
Test ()
{
printf ("Test Function called!\n");
}
#include <windows.h>
BOOL WINAPI
DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
printf ("DLL Attached.\n");
break;
case DLL_PROCESS_DETACH:
printf ("DLL Detached.\n");
break;
case DLL_THREAD_ATTACH:
printf ("DLL Thread Attached.\n");
break;
case DLL_THREAD_DETACH:
printf ("DLL Thread Detached.\n");
break;
}
return TRUE;
}
void
Test ()
{
printf ("Test Function called!\n");
}

View File

@ -1,44 +1,44 @@
//
// This is a C++ version of the code in dll.c. NOTE that you need to put
// extern "C" { ... } around DllMain or it will not be called when your
// Dll starts up! (It will get name mangled as a C++ function and the C
// default version in libmingw32.a will get called instead.)
//
#include <windows.h>
#include <iostream>
extern "C" {
BOOL WINAPI
DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
cout << "Dll Attached" << endl ;
break;
case DLL_PROCESS_DETACH:
cout << "Dll Detached" << endl ;
break;
case DLL_THREAD_ATTACH:
printf ("DLL Thread Attached.\n");
break;
case DLL_THREAD_DETACH:
printf ("DLL Thread Detached.\n");
break;
}
return TRUE;
}
void
Test ()
{
printf ("Test Function called!\n");
}
};
//
// This is a C++ version of the code in dll.c. NOTE that you need to put
// extern "C" { ... } around DllMain or it will not be called when your
// Dll starts up! (It will get name mangled as a C++ function and the C
// default version in libmingw32.a will get called instead.)
//
#include <windows.h>
#include <iostream>
extern "C" {
BOOL WINAPI
DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
cout << "Dll Attached" << endl ;
break;
case DLL_PROCESS_DETACH:
cout << "Dll Detached" << endl ;
break;
case DLL_THREAD_ATTACH:
printf ("DLL Thread Attached.\n");
break;
case DLL_THREAD_DETACH:
printf ("DLL Thread Detached.\n");
break;
}
return TRUE;
}
void
Test ()
{
printf ("Test Function called!\n");
}
};

View File

@ -1,2 +1,2 @@
EXPORTS
Test
EXPORTS
Test

View File

@ -1,13 +1,13 @@
#include <stdio.h>
extern void Test();
int main()
{
printf ("Program started.\n");
Test ();
printf ("Program ends.\n");
return 0;
}
#include <stdio.h>
extern void Test();
int main()
{
printf ("Program started.\n");
Test ();
printf ("Program ends.\n");
return 0;
}

View File

@ -1,14 +1,14 @@
Dll dll.dll : dll.c ;
ImportLib libdll.a : dll.def ;
Main exe.exe : exe.c ;
LinkLibraries exe.exe : libdll.a ;
DEPENDS exe.exe : dll.dll ;
LINKFLAGS on exe.exe = $(LINKFLAGS) -L. ;
Dll dll.dll : dll.c ;
ImportLib libdll.a : dll.def ;
Main exe.exe : exe.c ;
LinkLibraries exe.exe : libdll.a ;
DEPENDS exe.exe : dll.dll ;
LINKFLAGS on exe.exe = $(LINKFLAGS) -L. ;

View File

@ -1,9 +1,9 @@
#
# A very simple example with which you can test your compiler/jam setup.
# Also an interesting example of a hybrid console/GUI application.
#
Main test.exe : test.c ;
GuiLibs test.exe ;
#
# A very simple example with which you can test your compiler/jam setup.
# Also an interesting example of a hybrid console/GUI application.
#
Main test.exe : test.c ;
GuiLibs test.exe ;

View File

@ -1,20 +1,20 @@
/*
* This source code is in the PUBLIC DOMAIN and has NO WARRANTY.
*
* Colin Peters <colin@bird.fu.is.saga-u.ac.jp>, April 15, 1997.
*/
#include <windows.h>
#include <stdio.h>
int STDCALL
WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
{
char text[80];
printf ("Enter message box text:");
fgets(text, 80, stdin);
MessageBox (NULL, text, "Test", MB_OK);
printf ("\nHello after message box.\n");
return 0;
}
/*
* This source code is in the PUBLIC DOMAIN and has NO WARRANTY.
*
* Colin Peters <colin@bird.fu.is.saga-u.ac.jp>, April 15, 1997.
*/
#include <windows.h>
#include <stdio.h>
int STDCALL
WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
{
char text[80];
printf ("Enter message box text:");
fgets(text, 80, stdin);
MessageBox (NULL, text, "Test", MB_OK);
printf ("\nHello after message box.\n");
return 0;
}

View File

@ -1,8 +1,8 @@
#
# A example of Win32 GUI programming in C.
#
Main test.exe : test.c ;
Gui test.exe ;
#
# A example of Win32 GUI programming in C.
#
Main test.exe : test.c ;
Gui test.exe ;

View File

@ -1,212 +1,212 @@
/*
* A basic example of Win32 programming in C.
*
* This source code is in the PUBLIC DOMAIN and has NO WARRANTY.
*
* Colin Peters <colin@bird.fu.is.saga-u.ac.jp>
*/
#include <windows.h>
#include <string.h>
/*
* This is the window function for the main window. Whenever a message is
* dispatched using DispatchMessage (or sent with SendMessage) this function
* gets called with the contents of the message.
*/
LRESULT CALLBACK
MainWndProc (HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
/* The window handle for the "Click Me" button. */
static HWND hwndButton = 0;
static int cx, cy; /* Height and width of our button. */
HDC hdc; /* A device context used for drawing */
PAINTSTRUCT ps; /* Also used during window drawing */
RECT rc; /* A rectangle used during drawing */
/*
* Perform processing based on what kind of message we got.
*/
switch (nMsg)
{
case WM_CREATE:
{
/* The window is being created. Create our button
* window now. */
TEXTMETRIC tm;
/* First we use the system fixed font size to choose
* a nice button size. */
hdc = GetDC (hwnd);
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT));
GetTextMetrics (hdc, &tm);
cx = tm.tmAveCharWidth * 30;
cy = (tm.tmHeight + tm.tmExternalLeading) * 2;
ReleaseDC (hwnd, hdc);
/* Now create the button */
hwndButton = CreateWindow (
"button", /* Builtin button class */
"Click Here",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
0, 0, cx, cy,
hwnd, /* Parent is this window. */
(HMENU) 1, /* Control ID: 1 */
((LPCREATESTRUCT) lParam)->hInstance,
NULL
);
return 0;
break;
}
case WM_DESTROY:
/* The window is being destroyed, close the application
* (the child button gets destroyed automatically). */
PostQuitMessage (0);
return 0;
break;
case WM_PAINT:
/* The window needs to be painted (redrawn). */
hdc = BeginPaint (hwnd, &ps);
GetClientRect (hwnd, &rc);
/* Draw "Hello, World" in the middle of the upper
* half of the window. */
rc.bottom = rc.bottom / 2;
DrawText (hdc, "Hello, World", -1, &rc,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint (hwnd, &ps);
return 0;
break;
case WM_SIZE:
/* The window size is changing. If the button exists
* then place it in the center of the bottom half of
* the window. */
if (hwndButton &&
(wParam == SIZEFULLSCREEN ||
wParam == SIZENORMAL)
)
{
rc.left = (LOWORD(lParam) - cx) / 2;
rc.top = HIWORD(lParam) * 3 / 4 - cy / 2;
MoveWindow (
hwndButton,
rc.left, rc.top, cx, cy, TRUE);
}
break;
case WM_COMMAND:
/* Check the control ID, notification code and
* control handle to see if this is a button click
* message from our child button. */
if (LOWORD(wParam) == 1 &&
HIWORD(wParam) == BN_CLICKED &&
(HWND) lParam == hwndButton)
{
/* Our button was clicked. Close the window. */
DestroyWindow (hwnd);
}
return 0;
break;
}
/* If we don't handle a message completely we hand it to the system
* provided default window function. */
return DefWindowProc (hwnd, nMsg, wParam, lParam);
}
int STDCALL
WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
{
HWND hwndMain; /* Handle for the main window. */
MSG msg; /* A Win32 message structure. */
WNDCLASSEX wndclass; /* A window class structure. */
char* szMainWndClass = "WinTestWin";
/* The name of the main window class */
/*
* First we create a window class for our main window.
*/
/* Initialize the entire structure to zero. */
memset (&wndclass, 0, sizeof(WNDCLASSEX));
/* This class is called WinTestWin */
wndclass.lpszClassName = szMainWndClass;
/* cbSize gives the size of the structure for extensibility. */
wndclass.cbSize = sizeof(WNDCLASSEX);
/* All windows of this class redraw when resized. */
wndclass.style = CS_HREDRAW | CS_VREDRAW;
/* All windows of this class use the MainWndProc window function. */
wndclass.lpfnWndProc = MainWndProc;
/* This class is used with the current program instance. */
wndclass.hInstance = hInst;
/* Use standard application icon and arrow cursor provided by the OS */
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
/* Color the background white */
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
/*
* Now register the window class for use.
*/
RegisterClassEx (&wndclass);
/*
* Create our main window using that window class.
*/
hwndMain = CreateWindow (
szMainWndClass, /* Class name */
"Hello", /* Caption */
WS_OVERLAPPEDWINDOW, /* Style */
CW_USEDEFAULT, /* Initial x (use default) */
CW_USEDEFAULT, /* Initial y (use default) */
CW_USEDEFAULT, /* Initial x size (use default) */
CW_USEDEFAULT, /* Initial y size (use default) */
NULL, /* No parent window */
NULL, /* No menu */
hInst, /* This program instance */
NULL /* Creation parameters */
);
/*
* Display the window which we just created (using the nShow
* passed by the OS, which allows for start minimized and that
* sort of thing).
*/
ShowWindow (hwndMain, nShow);
UpdateWindow (hwndMain);
/*
* The main message loop. All messages being sent to the windows
* of the application (or at least the primary thread) are retrieved
* by the GetMessage call, then translated (mainly for keyboard
* messages) and dispatched to the appropriate window procedure.
* This is the simplest kind of message loop. More complex loops
* are required for idle processing or handling modeless dialog
* boxes. When one of the windows calls PostQuitMessage GetMessage
* will return zero and the wParam of the message will be filled
* with the argument to PostQuitMessage. The loop will end and
* the application will close.
*/
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
/*
* A basic example of Win32 programming in C.
*
* This source code is in the PUBLIC DOMAIN and has NO WARRANTY.
*
* Colin Peters <colin@bird.fu.is.saga-u.ac.jp>
*/
#include <windows.h>
#include <string.h>
/*
* This is the window function for the main window. Whenever a message is
* dispatched using DispatchMessage (or sent with SendMessage) this function
* gets called with the contents of the message.
*/
LRESULT CALLBACK
MainWndProc (HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
/* The window handle for the "Click Me" button. */
static HWND hwndButton = 0;
static int cx, cy; /* Height and width of our button. */
HDC hdc; /* A device context used for drawing */
PAINTSTRUCT ps; /* Also used during window drawing */
RECT rc; /* A rectangle used during drawing */
/*
* Perform processing based on what kind of message we got.
*/
switch (nMsg)
{
case WM_CREATE:
{
/* The window is being created. Create our button
* window now. */
TEXTMETRIC tm;
/* First we use the system fixed font size to choose
* a nice button size. */
hdc = GetDC (hwnd);
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT));
GetTextMetrics (hdc, &tm);
cx = tm.tmAveCharWidth * 30;
cy = (tm.tmHeight + tm.tmExternalLeading) * 2;
ReleaseDC (hwnd, hdc);
/* Now create the button */
hwndButton = CreateWindow (
"button", /* Builtin button class */
"Click Here",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
0, 0, cx, cy,
hwnd, /* Parent is this window. */
(HMENU) 1, /* Control ID: 1 */
((LPCREATESTRUCT) lParam)->hInstance,
NULL
);
return 0;
break;
}
case WM_DESTROY:
/* The window is being destroyed, close the application
* (the child button gets destroyed automatically). */
PostQuitMessage (0);
return 0;
break;
case WM_PAINT:
/* The window needs to be painted (redrawn). */
hdc = BeginPaint (hwnd, &ps);
GetClientRect (hwnd, &rc);
/* Draw "Hello, World" in the middle of the upper
* half of the window. */
rc.bottom = rc.bottom / 2;
DrawText (hdc, "Hello, World", -1, &rc,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint (hwnd, &ps);
return 0;
break;
case WM_SIZE:
/* The window size is changing. If the button exists
* then place it in the center of the bottom half of
* the window. */
if (hwndButton &&
(wParam == SIZEFULLSCREEN ||
wParam == SIZENORMAL)
)
{
rc.left = (LOWORD(lParam) - cx) / 2;
rc.top = HIWORD(lParam) * 3 / 4 - cy / 2;
MoveWindow (
hwndButton,
rc.left, rc.top, cx, cy, TRUE);
}
break;
case WM_COMMAND:
/* Check the control ID, notification code and
* control handle to see if this is a button click
* message from our child button. */
if (LOWORD(wParam) == 1 &&
HIWORD(wParam) == BN_CLICKED &&
(HWND) lParam == hwndButton)
{
/* Our button was clicked. Close the window. */
DestroyWindow (hwnd);
}
return 0;
break;
}
/* If we don't handle a message completely we hand it to the system
* provided default window function. */
return DefWindowProc (hwnd, nMsg, wParam, lParam);
}
int STDCALL
WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
{
HWND hwndMain; /* Handle for the main window. */
MSG msg; /* A Win32 message structure. */
WNDCLASSEX wndclass; /* A window class structure. */
char* szMainWndClass = "WinTestWin";
/* The name of the main window class */
/*
* First we create a window class for our main window.
*/
/* Initialize the entire structure to zero. */
memset (&wndclass, 0, sizeof(WNDCLASSEX));
/* This class is called WinTestWin */
wndclass.lpszClassName = szMainWndClass;
/* cbSize gives the size of the structure for extensibility. */
wndclass.cbSize = sizeof(WNDCLASSEX);
/* All windows of this class redraw when resized. */
wndclass.style = CS_HREDRAW | CS_VREDRAW;
/* All windows of this class use the MainWndProc window function. */
wndclass.lpfnWndProc = MainWndProc;
/* This class is used with the current program instance. */
wndclass.hInstance = hInst;
/* Use standard application icon and arrow cursor provided by the OS */
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
/* Color the background white */
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
/*
* Now register the window class for use.
*/
RegisterClassEx (&wndclass);
/*
* Create our main window using that window class.
*/
hwndMain = CreateWindow (
szMainWndClass, /* Class name */
"Hello", /* Caption */
WS_OVERLAPPEDWINDOW, /* Style */
CW_USEDEFAULT, /* Initial x (use default) */
CW_USEDEFAULT, /* Initial y (use default) */
CW_USEDEFAULT, /* Initial x size (use default) */
CW_USEDEFAULT, /* Initial y size (use default) */
NULL, /* No parent window */
NULL, /* No menu */
hInst, /* This program instance */
NULL /* Creation parameters */
);
/*
* Display the window which we just created (using the nShow
* passed by the OS, which allows for start minimized and that
* sort of thing).
*/
ShowWindow (hwndMain, nShow);
UpdateWindow (hwndMain);
/*
* The main message loop. All messages being sent to the windows
* of the application (or at least the primary thread) are retrieved
* by the GetMessage call, then translated (mainly for keyboard
* messages) and dispatched to the appropriate window procedure.
* This is the simplest kind of message loop. More complex loops
* are required for idle processing or handling modeless dialog
* boxes. When one of the windows calls PostQuitMessage GetMessage
* will return zero and the wParam of the message will be filled
* with the argument to PostQuitMessage. The loop will end and
* the application will close.
*/
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}