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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,39 +1,39 @@
This directory contains two examples of building DLLs. The exe.c and dll.c 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 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 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 exe.c program links to the DLL and prints the results of the function
call. call.
The C++ example "silly" is more interesting because it involves a DLL which 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 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 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 silly.cpp source code builds the main silly.exe executable which makes a
dynamic instance of the object and calls its member functions. 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 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 was generated and then getting the symbol names from that. Removing the
leading underscore produces the appropriate name to include in the EXPORTS leading underscore produces the appropriate name to include in the EXPORTS
section. Notice there are a few weird functions. section. Notice there are a few weird functions.
Since there are now several different versions of the GNU compiler capable 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 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 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 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 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 of GCC. The Cygnus version is different again, if I recall correctly, but I
don't have it hanging around anymore. don't have it hanging around anymore.
The jamfile builds all the components from the raw sources. 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 The expected output of exe.exe and silly.exe are in the files exe.exp
and silly.exp. and silly.exp.
The source code in this directory is in the PUBLIC DOMAIN and can be 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, used or abused as you see fit. There is NO WARRANTY for this code,
including (but not limited to) implied warranties of MERCHANTABILITY including (but not limited to) implied warranties of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. or FITNESS FOR A PARTICULAR PURPOSE.
Colin Peters <colin@bird.fu.is.saga-u.ac.jp> 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. // C++ test of a dll which contains a C++ class.
// //
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
// Interface of class. // Interface of class.
#include "silly.h" #include "silly.h"
#ifdef DERIVED_TEST #ifdef DERIVED_TEST
// Here is a derived class too. // Here is a derived class too.
class CMoreSilly : public CSilly class CMoreSilly : public CSilly
{ {
public: public:
CMoreSilly (char* szNewName) : CSilly (szNewName) {}; CMoreSilly (char* szNewName) : CSilly (szNewName) {};
~CMoreSilly (); ~CMoreSilly ();
WhatsYourName(); WhatsYourName();
}; };
CMoreSilly:: CMoreSilly::
~CMoreSilly () ~CMoreSilly ()
{ {
printf ("In CMoreSilly \"%s\" destructor!\n", szName); printf ("In CMoreSilly \"%s\" destructor!\n", szName);
} }
CMoreSilly:: CMoreSilly::
WhatsYourName () WhatsYourName ()
{ {
printf ("I'm more silly and my name is \"%s\"\n", szName); printf ("I'm more silly and my name is \"%s\"\n", szName);
} }
#endif #endif
int int
main () main ()
{ {
CSilly* psilly = new CSilly("silly"); CSilly* psilly = new CSilly("silly");
psilly->WhatsYourName(); psilly->WhatsYourName();
psilly->Poke(); // Poke him, he should say "Ouch!" psilly->Poke(); // Poke him, he should say "Ouch!"
psilly->Stab(4); // Stab him four times he should say "Ugh!!!!" psilly->Stab(4); // Stab him four times he should say "Ugh!!!!"
delete psilly; delete psilly;
#ifdef DERIVED_TEST #ifdef DERIVED_TEST
psilly = new CMoreSilly("more silly"); psilly = new CMoreSilly("more silly");
psilly->WhatsYourName(); psilly->WhatsYourName();
psilly->Stab(5); psilly->Stab(5);
delete psilly; delete psilly;
#endif #endif
return 0; return 0;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
Main test.exe : test.c ; Main test.exe : test.c ;
Main all.exe : all.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 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 default file opening mode (text vs. binary) and/or the mode of the standard
file handles. file handles.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,33 +1,33 @@
#include <windows.h> #include <windows.h>
BOOL WINAPI BOOL WINAPI
DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{ {
switch (dwReason) switch (dwReason)
{ {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
printf ("DLL Attached.\n"); printf ("DLL Attached.\n");
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
printf ("DLL Detached.\n"); printf ("DLL Detached.\n");
break; break;
case DLL_THREAD_ATTACH: case DLL_THREAD_ATTACH:
printf ("DLL Thread Attached.\n"); printf ("DLL Thread Attached.\n");
break; break;
case DLL_THREAD_DETACH: case DLL_THREAD_DETACH:
printf ("DLL Thread Detached.\n"); printf ("DLL Thread Detached.\n");
break; break;
} }
return TRUE; return TRUE;
} }
void void
Test () Test ()
{ {
printf ("Test Function called!\n"); 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 // 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 // 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 // Dll starts up! (It will get name mangled as a C++ function and the C
// default version in libmingw32.a will get called instead.) // default version in libmingw32.a will get called instead.)
// //
#include <windows.h> #include <windows.h>
#include <iostream> #include <iostream>
extern "C" { extern "C" {
BOOL WINAPI BOOL WINAPI
DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{ {
switch (dwReason) switch (dwReason)
{ {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
cout << "Dll Attached" << endl ; cout << "Dll Attached" << endl ;
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
cout << "Dll Detached" << endl ; cout << "Dll Detached" << endl ;
break; break;
case DLL_THREAD_ATTACH: case DLL_THREAD_ATTACH:
printf ("DLL Thread Attached.\n"); printf ("DLL Thread Attached.\n");
break; break;
case DLL_THREAD_DETACH: case DLL_THREAD_DETACH:
printf ("DLL Thread Detached.\n"); printf ("DLL Thread Detached.\n");
break; break;
} }
return TRUE; return TRUE;
} }
void void
Test () Test ()
{ {
printf ("Test Function called!\n"); printf ("Test Function called!\n");
} }
}; };

View File

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

View File

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

View File

@ -1,14 +1,14 @@
Dll dll.dll : dll.c ; Dll dll.dll : dll.c ;
ImportLib libdll.a : dll.def ; ImportLib libdll.a : dll.def ;
Main exe.exe : exe.c ; Main exe.exe : exe.c ;
LinkLibraries exe.exe : libdll.a ; LinkLibraries exe.exe : libdll.a ;
DEPENDS exe.exe : dll.dll ; DEPENDS exe.exe : dll.dll ;
LINKFLAGS on exe.exe = $(LINKFLAGS) -L. ; 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. # A very simple example with which you can test your compiler/jam setup.
# Also an interesting example of a hybrid console/GUI application. # Also an interesting example of a hybrid console/GUI application.
# #
Main test.exe : test.c ; Main test.exe : test.c ;
GuiLibs test.exe ; GuiLibs test.exe ;

View File

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

View File

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

View File

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