home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CICA 1995 May
/
cica_0595_4.zip
/
cica_0595_4
/
UTIL
/
WINCMD78
/
WCL_EXT.ZIP
/
WCL_EXT.TXT
< prev
next >
Wrap
Text File
|
1994-05-30
|
13KB
|
288 lines
ADDING USER-DEFINED EXTENSIONS TO WCL
-------------------------------------
Over the past few months, I have received incessant requests for me to
provide support for user extensions to WCL. I have finally decided to
provide a simple interface or hook to WCL for Windows programmers so that
they can add their own commands. This provides endless opportunities for
extending the command set which I have provided as internal commands, since
such user extensions are treated as internal commands by WCL.
The interface I have provided is very simple, as long as the rules are
adhered to. It revolves around DLLs which must be created by the user, and
which export two USER FUNCTIONS that WCL will interface to (the DLLs can
export other functions as well, but WCL will only interface to two named
functions).
Rules
-----
1. The DLLs must be given the extension .WXX (instead of .DLL), and
must be compiled with the FAR directive (and for C/C++ programmers,
it must be "FAR Pascal").
2. The .WXX DLLs *must* be in the WCL directory (i.e., in the same
directory as WCL.EXE, WCLDLL.EXE, and BIGWCL.EXE).
3. [i] The first of the two user functions must be called IsValidCommand.
It takes a null terminated string as a parameter, and returns an
integer. This is the function that WCL polls to see if any command
that is not recognised by WCL is one that is recognised by the user
DLLs. It is only if after polling all the .WXX files and none of them
recognised the command that WCL will present a "command not found"
error message to the user.
In this scheme, when the user types a command, WCL looks for
the command in this order;
[a] from the list of command aliases
[b] from the list of WCL internal commands
[c] from the list of WCL .CBF batch files
[d] from .EXE, .COM, .BAT, programs in the "path"
[e] if the "command" is a file name, from the list
of associations in the "Extensions" part of WIN.INI
[f] from the list of .WXX DLL files found in the WCL
directory.
If the command is not found in any of these places, then an
error is reported "this command cannot be found". If the
command is found in a .WXX file, then the whole command line
is passed to that DLL's "UserProc()" function.
The user can jump directly the "[f]" above, by-passing all the
others, by typing "EXT" or "USERPROC" before the name of the
extension command that he/she wants to execute. This ensures
speedier access to extensions. Command aliases can be created
for frequently used extensions, with the "EXT" prefix to the
commands.
Since there may be any number of .WXX files in the WCL directory,
please ensure that this function is optimized for speed, and that
it returns as soon as possible. The whole command line typed at
the WCL prompt is passed to the IsValidCommand() function.
It is up to you to parse the command line in your DLL.
e.g.;
[a] In Borland PASCAL
Function IsValidCommand (Command : PChar) : Integer;
[b] In C/C++
int IsValidCommand (LPSTR Command);
RETURN CODE
-----------
0 = success - the command is recognised by this DLL
1 = error - the command is not recognised by this DLL.
If this function returns any value other than 0 then
WCL will not proceed any further with the particular DLL.
It will then proceed to the next DLL (if any).
If the command is recognised, you may also want to perform
some other initialization functions in this function.
[ii] The SECOND function which WCL will interface to is the main
function in your DLL. It takes TWO parameters. The first
parameter is an HWnd (this is where I pass the handle of the
WCL window to your DLL). The second parameter is a null terminated
string. It returns an INTEGER;
[a] In Borland PASCAL
Function UserProc (Wnd : HWnd; Var Parm : PChar) : Integer;
[b] In C/C++
int UserProc (HWND Wnd; LPSTR Parm);
(I am not sure whether the syntax here is correct!)
RETURN CODE
-----------
-1 = success - but do not print the contents of "Parm"
at the WCL window
0 = success - and print the contents of "Parm"
1 = error - and print the contents of "Parm"
> 1 = error - but do not print the contents of "Parm"
at the WCL window
*** Please NOTE that *each* USER DLL (those with the .WXX extension)
MUST have these 2 functions.
4. Because WCL passes the handle of the WCL window to your DLL in
the UserProc() function, you should be able to output text to the
WCL window. You can do this through TextOut() or some other function.
Using TextOut() here is probably a precarious thing, and does not seem
to be the best way to do this (at least, not in my tests) - but it can
be attempted anyway, and something can sometimes be directed to the
WCL window.
However, you are on your own here. The best I can do is provide the
handle to the WCL window. You can get its device context with a call
to GetDC() - (remember to call ReleaseDC() afterward!!!) - or you
can do with the window handle as you please.
5. If you want the output from the commands to be echoed in the WCL window,
you have to do 2 things;
[a] Let function UserProc() return ZERO or 1 (see above)
[b] Put whatever you want to be output at the WCL window into the
null terminated string that was passed as a parameter to
UserProc
If UserProc() returns 0 or 1, WCL will re-direct whatever it finds
in "Parm" to the WCL window, when your function returns. Note that the
output in the string is dumped to the WCL window exactly as it is. If you
want a formatted output, you have to format the null terminated string
yourself, in your function (eg by inserting carriage returns after every
60 characters).
If UserProc() returns a value less than 0 (eg -1) or greater than 1 then
nothing will be written to the WCL window.
This is the ONLY thing that WCL uses the return value of UserProc() for.
Subject to what I have said above, it can return ANYTHING.
RESTRICTIONS
------------
User extensions in .WXX DLL files cannot be called from WCL batch
files.
Comments
--------
I have decided to use this method of providing hooks for other programmers
for a number of reasons. First, it is straightforward. Secondly, it does not
add much to the bulk of WCL itself - something I have to take seriously,
because most of my users are not programmers and are not interested in this
feature.
I expect the function UserProc() to be used as a "container" or "interface"
function only - although you can use it as you please. What I really
envisage is that programmers can define any number of functions and commands
in their DLLs, and that they will use the function UserProc() as their
"command line", which they will then parse, and then call other functions in
the DLL or elsewhere as may be necessary.
Check this pseudo code;
{------------------------------------------------------------}
function UserProc (Wnd : HWnd; Var Parm : PChar) : integer;
begin UserProc
if Parm = "SHUTDOWN" then call function ONE
else
if Parm = "OK" then call function TWO
else
if Parm = "MAKE_NOISE" then call MessageBeep (0)
else
if Parm = "DISK_FORMAT" then WinExec("D_FORMAT.EXE", sw_Normal)
else
MessageBox(Wnd, 'Not, Not, Not', 'Hello', mb_ok);
{etc, etc, etc }
Return -1
end UserProc
{-----------------------------------------------------------}
For those programmers who need it, I have provided an interface to a number
of functions in WCLCODE2.DLL, which comes standard with WCL. These are
string functions - to break up the "Parm" string parameter into as many
substrings as are found in it (up to 20) and return the number of such
substrings. This way, it is easy to parse the parameter passed to the
UserProc function.
eg if you passed "BPC -CW MYPROG.PAS /$F+ /L /$N+" in "Parm", calling the
function BreakString() will return 6 (there are 6 substrings in this
string) and the 6 substrings will be returned in an array.
These string functions were originally written to process Pascal type
strings only, but I have added equivalents for null terminated strings so
that C/C++ users can use the same functions. I have provided a Borland
Pascal interface unit (WCL_INT.PAS) for these functions, which contains all
the declarations, and the ordinal numbers of the functions, etc. Pascal
programmers can just add this unit to their USES clause, and start using the
functions right away.
C/C++ programmers will have to create a header file using the supplied
information, and also a LIB file for WCLCODE2.DLL, using their compiler's
IMPLIB utility. If anybody does this successfully, please send me a copy of
the header file, and of the LIB file (indicating what compiler this was
created for).
NOTE: ONLY *ONE* INSTANCE OF WCL CAN USE WCLCODE2.DLL AT ANY PARTICULAR
TIME BECAUSE OF SHARED MEMORY.
I have provided a sample .WXX DLL file (WCLMAP.WXX) - which implements
one command "WCLMAP" - a subset of the Netware MAP command. Please do
NOT attempt to run the WCLMAP command if you are not on a Netware network.
You are CERTAIN to get a General Protection Fault if you try it.
I have also provided the Pascal source code to a working (but virtually
useless) .WXX DLL file (WCL_EXT.PAS), which uses the parsing functions
I referred to above. This is supplied just as an example - to see what
types of things you could do in your DLL.
NOTES
------
1. A .WXX file is a normal Windows DLL, and should be compiled as
such. After compilation, then you change the extension to .WXX
(from .DLL), and you place it in the WCL directory.
2. Permission to use this interface to WCL is given on the basis
that the interface is being used for each person's own PERSONAL AND
PRIVATE use. You can obviously freely distribute your own extension DLLs
and any of your own binaries and documentation that complement it,
but ONLY as a package which is totally SEPARATE from the WCL package.
3. I envisage that if this interface becomes well established, people
might want to write "custom" WCL extension packages, which others can
then download from ftp sites.
4. Please do NOT attempt to distribute the WCL program with your own
extensions package - any attempt to do this WILL be a breach of
my copyright. If people want to use your extensions with WCL, then
they should get a copy of WCL as distributed by me, through the
normal distribution channels, and THEN they should get your extensions
for themselves (meaning that I don't want to take the blame or the
credit for other people's work - and I want it to be ABSOLUTELY CLEAR
what was distributed by me and what wasn't).
5. If you write extensions DLLs which you then wish to distribute as an
add-on to WCL, you should distribute ONLY your own binaries and
documentation, and ALSO, please do the following;
Include in your documentation for your extensions CLEAR AND
CONSPICUOUS MESSAGES,
(i) OF YOUR ACCEPTANCE OF TOTAL RESPONSIBILITY FOR ANY LOSS OR
DAMAGE CAUSED BY YOUR EXTENSIONS, AND ABSOLVING ME OF ALL
RESPONSIBILITY THEREFOR, and
(ii) THAT ALL QUESTIONS ABOUT YOUR EXTENSIONS AND THEIR EFFECT
ON WCL OR ON WINDOWS, SHOULD BE DIRECTED TO YOU, AND NOT
TO ME.
DISCLAIMER
----------
I AM SUPPLYING THIS INTERFACE ONLY AS A SERVICE TO USERS. I ACCEPT
ABSOLUTELY NO RESPONSIBILITY FOR ANY LOSS OR DAMAGE OR LOSS CAUSED
OR SUFFERED AS A RESULT OF THE USE OR THE PURPORTED USE OF THIS
INTERFACE, FOR ANY PURPOSE WHATSOEVER.
IF THESE TERMS ARE NOT ACCEPTABLE TO YOU, THEN YOU HAVE NO LICENSE
TO USE THIS INTERFACE TO WCL, AND YOU SHOULD NEVER ATTEMPT IT.
FURTHERMORE, I WILL ANSWER ABSOLUTELY NO QUESTIONS ABOUT THIS INTERFACE
FROM ANYBODY WHO HAS NOT REGISTERED HIS/HER COPY OF WCL. YOU WILL ALL
APPRECIATE THAT SINCE THERE ARE NO FREE LUNCHES, I CAN ONLY SUPPORT
REGISTERED USERS.
Dr. A. Olowofoyeku
June 1994.