Merging MinGW changes
This commit is contained in:
parent
ad39fa8cb0
commit
4ad1e6fedb
@ -1,3 +1,3 @@
|
||||
|
||||
Main test.exe : test.c ;
|
||||
|
||||
|
||||
Main test.exe : test.c ;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
EXPORTS
|
||||
Add
|
||||
Sub@16
|
||||
EXPORTS
|
||||
Add
|
||||
Sub@16
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
EXPORTS
|
||||
ExportedFromExe
|
||||
EXPORTS
|
||||
ExportedFromExe
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
|
||||
Main filehand.exe : filehand.c ;
|
||||
|
||||
|
||||
Main filehand.exe : filehand.c ;
|
||||
|
||||
|
@ -1 +1 @@
|
||||
This is a test file.
|
||||
This is a test 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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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).
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
Main test.exe : test.c ;
|
||||
|
||||
Main all.exe : all.c ;
|
||||
|
||||
|
||||
Main test.exe : test.c ;
|
||||
|
||||
Main all.exe : all.c ;
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 ;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
EXPORTS
|
||||
WalkExceptionHandlers
|
||||
DumpExceptionRecord
|
||||
EXPORTS
|
||||
WalkExceptionHandlers
|
||||
DumpExceptionRecord
|
||||
|
@ -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
|
||||
|
@ -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 ;
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -1,2 +1,2 @@
|
||||
EXPORTS
|
||||
Test
|
||||
EXPORTS
|
||||
Test
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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. ;
|
||||
|
||||
|
@ -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 ;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 ;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user