In your Extender Project directory, and in the RELEASE and DEBUG directories, delete the old DLLs and also any files with a 32i extension and possibly other temp OBJ files and stuff, as we will be changing the name of the output file to 34I in subsequent steps.
In Visual C, settings, LINK tab, change the output file name for BOTH Release and Debug builds from xxx.32i.dll to xxx.34i.dll
In Visual C, settings, C/C++ tab, "Code Generation" item in the dropdown box, set "Struct Member Alignment" to 4 bytes in BOTH Release and Debug builds
- Update fileversion information to match extender version information
- Update product version to 2001
- Update Copyright notice to 2001
- Update original filename so it shows the 34i extension
- update internal name so it show the 34i extension
String table string number 1000 should be a short description of the extender
In your source code increment the EXTENDERVERSION define to the next number
Add the INTERFACELEFEL define to your code someplace. Usually top of C program or H file someplace.If you do not have EXTENDER_FEATURE_LEVEL in your code add it in.
#define INTERFACELEVEL 2 // extender interface level (DON'T CHANGE!) #define EXTENDER_FEATURE_LEVEL 1001 // required BATDLL feature interface level
Delete existing RET* macros
Replace with following:
#define RETLONG(numb) return (lpViperCallback(((lpViperReturn->x=numb) +(lpViperReturn->inittype=VARTYPE_INT)) ?RESULT_SUCCESS:RESULT_SUCCESS, ViperInterfaceVersion, lpViperStruct, lpViperReturn)) #define RETFLOAT(numb) return (lpViperCallback(((lpViperReturn->flt=numb) +(lpViperReturn->inittype=VARTYPE_FLOATNUM)) ?RESULT_SUCCESS:RESULT_SUCCESS, ViperInterfaceVersion, lpViperStruct, lpViperReturn)) #define RETSTRING(str) return (lpViperCallback(((lpViperReturn->lpstr=str) +(lpViperReturn->inittype=VARTYPE_STRING)) ?RESULT_SUCCESS:RESULT_SUCCESS, ViperInterfaceVersion, lpViperStruct, lpViperReturn)) #define RETERROR(sev, errnum) return (lpViperCallback(((LoadString(hinstDLL, (errnum), lpViperReturn->lpstr = szWork, sizeof(szWork)))+(lpViperReturn->inittype = VARTYPE_STRING)) ?(sev) :(sev) , ViperInterfaceVersion, lpViperStruct, lpViperReturn)) #define ANSWERSTRING(str) lpViperCallback( ((lpViperReturn->lpstr=str)+(lpViperReturn->inittype=VARTYPE_STRING))?RESULT_SUCCESS:RESULT_SUCCESS,ViperInterfaceVersion,lpViperStruct,lpViperReturn) #define ANSWERLONG(numb) lpViperCallback( ((lpViperReturn->x=numb)+(lpViperReturn->inittype=VARTYPE_INT))?RESULT_SUCCESS:RESULT_SUCCESS,ViperInterfaceVersion,lpViperStruct,lpViperReturn) #define ANSWERFLOAT(numb) lpViperCallback( ((lpViperReturn->flt=numb)+(lpViperReturn->inittype=VARTYPE_FLOATNUM))?RESULT_SUCCESS:RESULT_SUCCESS,ViperInterfaceVersion,lpViperStruct,lpViperReturn) #define RETCANCEL return (-5)
- Change CommandExtTable type from COMMEXTSTRUCT to tablestruct
It should read...
tablestruct CommandExtTable[] =
- Convert CONSTANT entries in CommandExtTable: Basically change
CONSTANT,toCONSTANT, 0x0000000000000000,
- Convert FUNCTION entries in CommandExtTable:
Old: {10, FUNCTION, 0x001F0001L, 0, "xextenderinfo"}, New: {10, FUNCTION, 0x0000000000011111, 0x00000001L, 0, "xExtenderInfo"},Note that a quick way to do it is to replace
with0x001F000
0x0000000000011111, 0x0000000
- Add
to the final -1 entry.0x0000000000000000
Basically copy and paste the following code someplace/*=========================================================================== WILExtenderQuery WILExtenderQuery is an optional (but recommended) entry point. It is used to provide helpful information to the WIL DLL and possibly other callers. ===========================================================================*/ DllExport LONG FAR PASCAL WILExtenderQuery (short nRequest, // type of information being requested LPVOID lpvInfo, // information buffer LONG nCount) // additional data { static char szWork[256]; LONG i; switch (nRequest) { /*--------------------------------------------------------------------------- case 1 is used to identify yourself to a caller. If lpvInfo is not NULL, it points to a character buffer where you may copy a string describing the extender. nCount is the size of the buffer pointed to by lpvInfo, in bytes. When called by the WIL DLL, you can expect this to be a 256-byte buffer. The return value should be the version number of the extender. ---------------------------------------------------------------------------*/ case 1: // version information { if ((lpvInfo) && (nCount > 0)) { LoadString(hinstDLL, 1000, szWork, sizeof(szWork)); lstrcpyn((LPSTR) lpvInfo, szWork, nCount); } return (EXTENDERVERSION); } /*--------------------------------------------------------------------------- case 2 is used to inform the WIL DLL of your preferred interface level. lpvInfo points to an array of LONG's, indicating the interface levels supported by the WIL DLL (each element represents one level). nCount indicates the number of elements in the array pointed to by lpvInfo. The return value must be the same as one of the elements in the lpvInfo array. Currently, the WIL DLL supports interface levels 1 and 2, so your return value should be 1 or 2. Newly designed extenders (such as WILX) use interface level 2 and have a WilExtender2 entry point. However, it is possible to design an extender to support multiple interface levels. If you return an invalid value, the extender will not be loaded and the AddExtender command will fail. ---------------------------------------------------------------------------*/ case 2: // preferred interface version { for (i = 0; i < nCount; i++) if (((LPLONG) lpvInfo)[i] == INTERFACELEVEL) // found one we like return (INTERFACELEVEL); return (-1); // didn't find any we like } /*--------------------------------------------------------------------------- Return 0 for any unknown requests, or any requests you don't handle! ---------------------------------------------------------------------------*/ default: return (0); } }
Rename your WilExtender function to WilExtender2 and change parameters. Basically use the NEW code belowOld:
DllExport LONG FAR PASCAL WILExtender (HWND hWnd, // handy hWnd for messageboxes, etc HINSTANCE hInst, // valid hInstance LONG lVersion, // don't touch short CmdId, // case number for big switch lpAddOnCallback lpPhoneHome, // don't touch LPSTR lpBlock, // don't touch LONG FAR * lpLong, // pointer to your 32 bits LPSTR lp1, // parameter 1 LPSTR lp2, // parameter 2 LPSTR lp3, // parameter 3 LPSTR lp4, // parameter 4 LPSTR lp5) // parameter 5New:
DllExport LONG FAR PASCAL WILExtender2 (HWND hWnd, // hWnd of parent application HINSTANCE hInst, // hInstance of parent application LONG ViperInterfaceVersion, // WIL interface version short CmdId, // identifies extender function being called LPVIPERCALLBACK lpViperCallback, // pointer to return value callback function LPVIPERSTRUCT lpViperStruct, // pointer to information structure LPLONG lpLong, // pointer to your 32 bits LPVIPERVAR lpvvArg, // pointer to parameter array LONG nArgCount, // parameter count for lpvvArg LPVIPERVAR lpViperReturn) // pointer to return value structure
In the WilExtender2 function add...LPSTR lp1, lp2, lp3, lp4, lp5;
This is for the "dumb" conversion to get stuff working ASAP. you might wish to revise this later when you make a complete conversionif (CmdId >= 0) // don't do this for initialization calls { lp1 = lpvvArg[0].lpstr; lp2 = lpvvArg[1].lpstr; lp3 = lpvvArg[2].lpstr; lp4 = lpvvArg[3].lpstr; lp5 = lpvvArg[4].lpstr; }Basically it is converting the new parameter passing stuff to look like the old way so you should not need to convert any functions.
If you had code in the extender checking the bInterfaceOK flag to determine if the DLL is compatible with the WIL version, delete it. Delete the bInterfaceOK GLOBAL variable also. All this work is done in the case -1 routine (described below)
Add case -1 to the switch statement. Paste code below. I like to organize my new switched likecase -1
case -2
case -3
case 0
case 1
etcMove any one-time initialization code that you were doing in case 98 into this new case -1 routine
/*--------------------------------------------------------------------------- Case -1 is called once, when your extender is loaded. It is the place to perform your one-time initialization tasks. The return value should be the number of items in your CommandExtTable (functions and constants). You may also return 0 if you are unable to determine the correct number of items. You may return a negative value (-1) to indicate that your extender was unable to successfully initialize, for example, if it is running on an unsupported platform or a dependent DLL could not be loaded. This will cause the AddExtender command to fail. You may additionally provide a string indicating the reason for the failure: lpvvArg points to a character buffer into which you may copy an error message. nArgCount is the size of the buffer pointed to by lpvvArg, in bytes. You can expect this to be a 256-byte buffer. ---------------------------------------------------------------------------*/ case -1: // Initialization { BOOL bInterfaceOk; bInterfaceOk=FALSE; if (lpViperStruct->dwLevel >= EXTENDER_FEATURE_LEVEL) { bInterfaceOk = TRUE; //lpfnDllServices = lpViperStruct->lpfnDllServices; //hBatData = lpViperStruct->hBatData; } if (bInterfaceOk==FALSE) { lstrcpy((LPSTR)lpvvArg,"Need newer version of WIL DLL"); return (-1); } //******* Add your one time initialization code here (if any) return ((sizeof(CommandExtTable) / sizeof(tablestruct)) - 1); // 1 extra at end }
In WILExtender2, change case 98 to case -2, and update the code that loads the table information. Consider moving case -2 under case -1.In most cases you may be able to delete case 98 and cut and past the following code.
/*--------------------------------------------------------------------------- Case -2 is called repeatedly by the WIL extender. On each call, one CommandTable entry is passed back to the WIL extender. It is unlikely that you will need to modify this code. ---------------------------------------------------------------------------*/ case -2: // Loading table { LPTABLESTRUCT lpTable; UINT j; lpTable = (LPTABLESTRUCT) lpvvArg; j = (UINT) nArgCount; if (CommandExtTable[j].ident == -1) return (0); if (lpTable) { lpTable->ident = CommandExtTable[j].ident; lpTable->type = CommandExtTable[j].type; lpTable->param1 = CommandExtTable[j].param1; lpTable->ulMask = CommandExtTable[j].ulMask; lpTable->size = lstrlen((LPSTR) CommandExtTable[j].delim); CharLower(CommandExtTable[j].delim); lstrcpy((LPSTR) lpTable->delim, (LPSTR) CommandExtTable[j].delim); } return (1); }In case 98, if you were accessing feature information passed as lp3, lp4, and lp5, that code needs to be updated. The relevant information is now passed as members of the LPVIPERSTRUCT structure. dwLevel can be checked in case -1. lpfnDllServices and hBatData can be saved to global variables in case -1, or used directly in any function that needs them.
In WILExtender2, change case 99 to case -3. Consider moving it under case -2
If you have a case 100, just delete it as it is now obsolete. Its functionality has moved to WILExtenderQuery, case 1.
// Addon.h Addon file for Wil 2001 AddOns typedef LPVOID LPBDS; // not really typedef LPVOID LPRESULTVAR; // not really typedef LONG (FARPASCAL * DLLSERVICES) (HGLOBAL, WORD, LPSTR, LPSTR, int, DWORD); typedef struct { LPBDS lpbdsptr; // pointer to lpBDS (internal use) LPRESULTVAR lprvptr; // WIL resultvar (internal use) DWORD dwLevel; // feature interface level DWORD dwSize; // size of the structure DLLSERVICES lpfnDllServices; // address of DLLServices function HGLOBAL hBatData; // buffer pointed to by lpBDS } VIPERSTRUCT, FAR *LPVIPERSTRUCT; typedef int FAR PASCAL AddOnCallback (int,LONG,LPSTR,BOOL,LONG,LPSTR); typedef AddOnCallback FAR *lpAddOnCallback; #define VARTYPE_UNDEF 0 // These are bitmapped, var can be both #define VARTYPE_INT 1 // Numeric and string, must check bits #define VARTYPE_STRING 2 #define VARTYPE_FILE 5 // FILE and INT bits set #define VARTYPE_OLEOBJECT 17 // OLE AND INT bits set #define VARTYPE_FLOATNUM 32 // floating point #define VARTYPE_BINARY 65 // BINARY and INT bits set #define VARTYPE_ARRAY 256 // an array typedef struct vipervariable { double flt; // 8-byte floating point number LONG x; // if int variable, value is here int inittype; // 0=uninitialized 1=int 2=string 3=both yes can have both sometimes union { LPSTR lpstr; // pointer to string in string table DWORD handle; // handle for miscellaneous object types }; } vipervar, FAR *LPVIPERVAR; typedef int FAR PASCAL ViperCallback (int,LONG,LPVIPERSTRUCT,LPVIPERVAR); typedef ViperCallback FAR *LPVIPERCALLBACK; #ifdef WIN32 #define DllExport __declspec(dllexport) DllExport LONG #else LONG #endif FAR PASCAL WILExtender2(HWND, HINSTANCE, LONG, short, LPVIPERCALLBACK, LPVIPERSTRUCT, LPLONG, LPVIPERVAR, LONG, LPVIPERVAR); #ifdef WIN32 #define DllExport __declspec(dllexport) DllExport LONG #else LONG #endif FAR PASCAL WILExtenderQuery(short, LPVOID, LONG); #define COMMEXT_WILSON 0x30030105L //------------------------------------------------------------------- // MISC. DEFINITIONS //------------------------------------------------------------------- #define FUNCTION 2 #define CONSTANT 3 #define RESULT_CALLBACK_ERROR -4 #define RESULT_FATAL_ERROR -3 #define RESULT_MODERATE_ERROR -2 #define RESULT_MINOR_ERROR -1 #define RESULT_SUCCESS 0 //------------------------------------------------------------------- //==== DELIMSIZE IS DEFINED BY INTERPRETER, DON'T CHANGE THIS! ====== //------------------------------------------------------------------- #define DELIMSIZE 30 #define KTDELIMSIZE 30 // Gives us 30 character function names. NO modify //------------------------------------------------------------------- // COMMAND EXTENSION STRUCTURES //------------------------------------------------------------------- typedef struct tableinfo { LONG ident; // delimindex - must be consecutive!!!!!! LONG type; // 2=FUNCTION 3=CONSTANT 4=COMMAND __int64 ulMask; // 64-bit mask (16 params, 4 bits each) LONG param1; // (funct ? hi(reserved) lo(num-args)) (constant ? value) short size; // length of function name char delim[KTDELIMSIZE + 1]; // funct/const name - must be lowercase! } tablestruct, FAR *LPTABLESTRUCT; //#define MBSS(p1, p2) {MessageBox(GetFocus(), (p2), (p1), MB_OK | MB_SETFOREGROUND);} //#define MBSN(p1, p2) {char szDebug[20]; MyLtoa((p2), szDebug, 10); MessageBox(GetFocus(), szDebug, (p1), MB_OK | MB_SETFOREGROUND);}
References to 32I in the help file, especially in ALL the AddExtender Lines in the examples should be updated to reflect the new 34I name of the DLL. In most cases simply searching for 32I and replacing that with 34I should do the trick.
The DAT files used by the old compiler have been renamed to EXT files. Verify the name change.Inside the new EXT file the filename of the extender dll should reflect the new 34I extension.
The readme file accompanying the extender should mention the name change and any other relevant items, like the incompatibility with previous version. E.G.
Ver 12345 Jan 11, 2001 The Wampwuzzy extender has been updated to a new format to allow more descriptive function names and additional parameters. This version of the extender requires WinBatch 2001A or newer to run. This extender will not work on WinBatch 2000C or older. In addition, so as not to affect existing scripts using a previous version of this extender, the extender DLL has been renamed to include a 34I in the DLL name instead of a 32I. Old and new versions of this extender can *usually* co-exist side by side. To use the new extender with old scripts and with WinBatch 2001A or newer you will need to change the AddExtender line in the script to reflect the new DLL name. e.g. AddExtender("wwabc32i.dll") should become AddExtender("wwabc34i.dll")
This process does a quick and dirty change of the extender to the new formats. With additional work the extender can be modified to accept parameters in "native" format rather than just accepting them as strings. When thus converted, the WIL Extnder can do parameter validation (ints will be ints, etc)