home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / fax067.zip / dll.doc < prev    next >
Text File  |  1997-04-14  |  11KB  |  315 lines

  1. First preliminary description of calling convention for
  2.  
  3. ANSW.DLL
  4. FREC.DLL
  5. FSEND.DLL
  6.  
  7. 1) OVERVIEW
  8.  
  9. All three DLLs are in behavior identical to their EXE counterparts.
  10.  
  11. While EXE is called with commandline parameters (or switches respectively
  12. options), DLL assumes a call to its internal (exported) entry function. This
  13. entryfunction (DllHandler) has two arguments and returns one value:
  14.  
  15. APIRET APIENTRY DllHandler(TXPARAM *txp,void *dummy);
  16.  
  17. The argument 'dummy' MUST BE NULL (a null pointer) otherwise, DllHandler
  18. assumes an other calling convention as described here!
  19.  
  20. The pointer 'txp' points to a structure of pointers to some optional and
  21. mandatory values or functions:
  22.  
  23. typedef struct {
  24.     BOOL (* APIENTRY Deb_Bin)(UCHAR *,int,int);
  25.     void (* APIENTRY Status)(CHAR *,USHORT);
  26.     void (* APIENTRY Update)(void *,int);
  27.     void **Extra;
  28.     char *Cmd;
  29.     } TXPARAM, *PTXPARAM;
  30.  
  31. Status and Cmd are mandatory values, if not supplied (null), DllHandler quits
  32. and returns (APIRET) 255.
  33.  
  34. Deb_Bin, Update and Extra are optional values and if not supplied, internal
  35. replacements will be used.
  36.  
  37. 2) DESCRIPTION of arguments of DllHandler
  38.  
  39. void APIENTRY Status(CHAR *line,USHORT sign);
  40.  
  41. 'line' is a zero limited string, its length can be maximal 2048 characters, but
  42. normally it is not more than 128 characters (as much as needed).
  43.  
  44. 'sign' is an ordinal number from 0 to 9 and has the following meaning:
  45.  
  46. 0 ... Received
  47. 1 ... Send
  48. 2 ... Wait
  49. 5 ... Info
  50. 6 ... Action
  51. 8 ... Error
  52. 9 ... Debug (only supplied if 'Debug' is set in applications CFG)
  53.  
  54. There are some RESTRICTIONS for this function!
  55.  
  56. It is recommended, to do not write directly to screen or to file system. It
  57. it recommended, to use an extra thread for all displaying and storing of
  58. Status. Communication between Status() and thread should be done via
  59. message queue.
  60.  
  61. Status flagged by 8 is normally not timecritical. If Status writes directly
  62. to screen, a redirection to a disk file should be avoided!
  63.  
  64. Please keep also in mind, that ANY thread of the DLL can call Status!
  65.  
  66. char *Cmd;
  67.  
  68. This is in fact the commandline, which would be supplied to the EXE.
  69.  
  70. This commandline MUST have valid entry for a configuration file
  71. (e.g. -cFREC.CFG) and the HANDLE of an already opened COM port (e.g. -p6).
  72.  
  73. It is also recommended, to supply a task number (e.g. -task1) to synchronize
  74. calling application with called DLL.
  75.  
  76. The supplied pointer MUST point to free space (max. 128 character) which will
  77. be filled by called DLL when finishing. Caller MUST save the value of the
  78. supplied pointer, because it may be replaced by NULL to signal certain
  79. condition!
  80.  
  81. BOOL APIENTRY Deb_Bin(UCHAR *content,int count,int sign);
  82.  
  83. This function is optional, and if not supplied (NULL), DLL will create its own
  84. Debug_Thread and write to it.
  85.  
  86. If calling application supplies this function, than it MUST handle calls to
  87. it via message queue to a dedicated thread, which is running under priority
  88. IDLETIME !!!
  89.  
  90. 'content' is a 'string' of bytes (0 - 255) of length 'count'. It MAY NOT be
  91. assumed that only printable characters are in this 'string'!
  92.  
  93. 'sign' has identical meaning as above, with the exception that also 9 is
  94. passed in each case!
  95.  
  96. Please keep in mind, that this function can deliver a huge amount of data
  97. (nearly ALL activities of DLL are 'logged' here).
  98.  
  99. void APIENTRY Update(void *value,int meaning);
  100.  
  101. This function may be only supplied if caller knows internals of DLL. AT this
  102. time, there exists no real 'standard', how this function acts (but it is
  103. called from DLL more often than Status).
  104.  
  105. The author is willing to accept a transparent handling of this function, but
  106. keep in mind, that 'handling' of this function needs also a dedicated thread,
  107. to which message queue (or WinPostMsg) is reporting.
  108.  
  109. The primary indention of this function is, to supply any kind of 'windows' of
  110. calling application with more or less meaningful information like:
  111.  
  112. time of transmission, byte count and length of receiving/sending files, some
  113. additional status information about session and much more.
  114.  
  115. It is recommended to supply NULL.
  116.  
  117. void **Extra;
  118.  
  119. This is a 'backdoor' for future expansions. Only one feature is implemented
  120. at this time;
  121.  
  122. void *MyExtra[2];
  123. char keyboardstatus;
  124.  
  125. MyExtra[0] = (void *) &keyboardstatus;
  126. MyExtra[1] = NULL;
  127.  
  128. Extra = MyExtra;
  129.  
  130. In fact, the DLL is supplied with a pointer to an array of (void) pointers,
  131. where the first one is a pointer to a character, which can transmit
  132. keyboardentries (or 0) to the called DLL. The DLL reacts for:
  133.  
  134. 0 ....     no reaction
  135. 27 ...     ESC, the string 'ERROR' is supplied to internal routines, as if it
  136.         comes from modem, also a global variable 'break_request' is set to TRUE
  137. 30 ...  the string 'RING' is supplied to internal routines, as if it comes
  138.         from modem. Can be used to manually initiate a call.
  139.  
  140. DLL itself uses this pointer to that character! If 27 or 30 is read, DLL sets
  141. the character to 0. Also (if value of character is 0) DLL may set it to any
  142. value to signalize internal.
  143.  
  144. DLL internal does absolutely NO CHECK to users keyboard or mouse activities.
  145. Therefore DLL can be used for textmode AND PM application!
  146.  
  147. In case of unusable (internal) function Deb_Bin, message is redirected to
  148. 'stderr' which should in any case be redirected (by '2>error.log') to a file
  149. to avoid damage of screen layout. Normally, 'stderr' is not used, but the only
  150. way for IMGPROC.DLL (which is called from FREC.DLL and FSEND.DLL) to
  151. report errors.
  152.  
  153. 3) DESCRIPTION of return of DllHandler
  154.  
  155. DllHandler simply returns the same value, as EXE will do by ErrorLevel.
  156.  
  157. But there is one additional feature, the EXE never can do:
  158.  
  159. The supplied pointer txp->Cmd is treated in dependence of what has happened.
  160.  
  161. If termination of DLL was incorrect or any error has occurred, txp->Cmd is
  162. set to NULL. Caller should cancel all further actions on this call.
  163.  
  164. If termination of DLL was in a state, where caller should continue, txp->Cmd
  165. is set to "" (empty string). Caller must continue, is if DLL never was called.
  166.  
  167. If DLL has done all its jobs and a special entry in CFG (MessageOk or PageOk)
  168. was found, the arguments of it are copied to txp->Cmd. As a result of the next
  169. described option, it is only meaningful to use a numerical value (e.g. for an
  170. errorlevel exit) here.
  171.  
  172. If DLL has detected a situation, where it had to do some job of caller, the
  173. last response of modem is supplied as a copy in txp->Cmd. Caller must act, as
  174. if this response was received by itself.
  175.  
  176. 4) EXAMPLE of implementing call to DllHandler
  177.  
  178. Assuming, we have a main 'listening' function, which has detected a certain
  179. modem response, on which it has decided, to call DllHandler.
  180.  
  181. Where 'modul' is the module name of the DLL (ANSW or FREC or FSEND) and 'cmd'
  182. some elsewhere supplied commandline parameters ...
  183.  
  184. HFILE hTTY; // the REAL handle for COM
  185. USHORT TaskNumber;
  186.  
  187. APIRET FeatureDLL(UCHAR *cmd, UCHAR *modul)
  188. {
  189. APIRET  ret,rc;
  190. CHAR    LoadError[100],cmdline[256];
  191. HMODULE ModuleHandle;
  192. ULONG   ProcType;
  193. TXPARAM txp;
  194. void    *Extra[2];
  195. APIRET (* APIENTRY DllHandler)(TXPARAM *,VOID *);
  196.  
  197. // clear it
  198. memset(&txp,0,sizeof(txp));
  199. #ifdef MAXCOMM
  200. hTTY = ComGetFH(hcModem);
  201. ComPause(hcModem);
  202. #endif
  203. // add porthandle to commandline
  204. sprintf(cmdline,"%s -p%u",cmd,hTTY);
  205. // if other than zero, add task#
  206. if (TaskNumber)
  207.     sprintf(&cmdline[strlen(cmdline)]," -task%hu",TaskNumber);
  208.  
  209. txp.Status  = status; // supply our function
  210. txp.Cmd     = cmdline; // supply this local buffer
  211.  
  212. ret = (APIRET) -1;
  213. rc = DosLoadModule(LoadError,sizeof(LoadError),module,&ModuleHandle);
  214. if (rc == 0)
  215.     {
  216.     rc = DosQueryProcType(ModuleHandle,1L,NULL,&ProcType);
  217.     if (rc == 0 && ProcType == PT_32BIT)
  218.         {
  219.         rc = DosQueryProcAddr(ModuleHandle,1L,NULL,
  220.             (PFN *) &DllHandler);
  221.         if (rc == 0)
  222.             {
  223.             ret = DllHandler(&txp,NULL);
  224.             }
  225.         }
  226.     DosFreeModule(ModuleHandle);
  227.     }
  228. #ifdef MAXCOMM
  229. ComResume(hcModem);
  230. #endif
  231. If (txp.Cmd) strcpy(cmd,txp.Cmd);
  232. else ret = (APIRET) -1; // in this case, ignore cmd
  233. return(ret);
  234. }
  235.  
  236. 5) CONCEPTIONAL Hints
  237.  
  238. The usefulness of a FeatureDLL is enormous. Not only (as described here)
  239. fax receive and transmission and answering machine are possible applications.
  240.  
  241. A FREECALL.DLL is already created by third party, and CALLERID.DLL is also
  242. an imaginable purpose.
  243.  
  244. If well implemented to front-end's modem listening routine, DllHandler can be
  245. called at incoming calls and at outgoing calls. Multiple calls to different
  246. modules are possible:
  247.  
  248. Modem response RING calls ANSW.DLL to distinguish between fax/dat/voice calls.
  249.  
  250. If voice call, ANSW.DLL do all the necessary job and returns with
  251. txp->Cmd = NULL to signalize, all over and out.
  252.  
  253. If fax calling tone is detected by ANSW, it can call FREC.DLL by itself or
  254. simply return with txp->Cmd = "", which signals to front-end to 'collect'
  255. further more modem responses. If front-end detects FAX or +FCO or +FCON it
  256. calls FREC.DLL which do all the fax job and even if a remote fax wants to poll
  257. FREC calls by itself FSEND.DLL to satisfy poll.
  258.  
  259. FREC returns normally with txp->Cmd = "" or txp->Cmd = "<number>".
  260.  
  261. ANSW also can return with txp->Cmd = "<number>" to signalize, front-end should
  262. act (e.g. by errorlevel exit) appropriate.
  263.  
  264. There is a special situation, if using modems from USR in conjunction with
  265. fax class 1 (which must be selected if modem should work as a fax receiver AND
  266. pollserver):
  267.  
  268. If front-end detects RING, it calls FREC (or even ANSW) with '-sWAIT_FCON'.
  269. FREC (or even ANSW) will issue the necessary
  270. 'AT+FCLASS=1<cr>AT+FAA=1<cr>AT+FCR=1<cr>ATA<cr>' to force adaptive autoanswer
  271. for class 1.
  272.  
  273. If a fax call arrives, FAX is detected and FREC will do its job and set
  274. txp->Cmd = NULL. If a datacall arrives, modem sends DATA to FREC, which
  275. 'knows' (by 'USRobotics' in CFG) that it should send 'ATO<cr>' to modem.
  276. From this point on, two conditions are possible:
  277.  
  278. Negotiation of data call is so fast, that FREC will receive the
  279. 'CONNECT 28800/ARQ' response (txp->Cmd = "CONNECT 28800/ARQ"), or if not,
  280. FREC will terminate and signalize wait for response (txp->Cmd = "").
  281.  
  282. There is no known front-end (mailer) which can do it, but it is worth to
  283. think about:
  284.  
  285. Front-end (mailer) dials a certain number and gets the response FAX or +FCO or
  286. +FCON (has in fact called a fax machine). Very simple to act on this:
  287.  
  288. Call FSEND.DLL and send. If called station has also a fax 'on hold', FSEND will
  289. recognize it and call FREC.DLL by itself.
  290.  
  291. Other situation (modem must be clever enough to detect VOICE):
  292.  
  293. Front-end (mailer) has called a human and should send a voice message, by
  294. calling ANSW.DLL. If 'human' is clever and switches his modem on-line, ANSW
  295. detects 'CONNECT XXXXX/Any' and simply returns with
  296. txp->Cmd = "CONNECT XXXX/Any" to signal front-end about the successful data
  297. connection .....
  298.  
  299. Same mechanism could be used, to implement FREEPOLL also for a caller (for
  300. called front-end there still exists a FREEPOLL.DLL).
  301.  
  302. Detection and solution of CallerID are also possible, and all the ISDN goodies.
  303.  
  304. Simply construct a FeatureDLL for the purpose you want ...
  305.  
  306.  
  307. Harald Pollack
  308.  
  309. Fido: 2:310/14.59
  310. I-Net: Harald.Pollack@omv.co.at
  311.  
  312. Bernhard Seidl
  313.  
  314. Fido: 2:310/14.5
  315.