Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

541 lines
11 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. t30util.c
  5. Abstract:
  6. Utilities for t30
  7. Author:
  8. Rafael Lisitsa (RafaelL) 2-Feb-1996
  9. Revision History:
  10. --*/
  11. #include "prep.h"
  12. #include "glbproto.h"
  13. #include "t30gl.h"
  14. #define IDVARSTRINGSIZE (sizeof(VARSTRING)+128)
  15. #define BAD_HANDLE(h) (!(h) || (h)==INVALID_HANDLE_VALUE)
  16. ///////////////////////////////////////////////////////////////////////////////////
  17. PVOID
  18. T30AllocThreadGlobalData(
  19. VOID
  20. )
  21. {
  22. PVOID pTG;
  23. pTG = MemAlloc (sizeof(ThrdGlbl) );
  24. FillMemory (pTG, sizeof(ThrdGlbl), 0);
  25. return (pTG);
  26. }
  27. /////////////////////////////////////////////////////////////
  28. BOOL itapi_async_setup(PThrdGlbl pTG)
  29. {
  30. EnterCriticalSection(&T30CritSection);
  31. if (pTG->fWaitingForEvent) {
  32. MyDebugPrint(pTG, LOG_ERR, "ERROR:Already waiting for event!\n");
  33. }
  34. if (pTG->dwSignalledRID) {
  35. MyDebugPrint(pTG, LOG_ERR, "ERROR:Nonzero old NONZERO ID 0x%lx\n",(unsigned long) pTG->dwSignalledRID);
  36. }
  37. pTG->fWaitingForEvent=TRUE;
  38. ResetEvent(pTG->hevAsync);
  39. LeaveCriticalSection(&T30CritSection);
  40. return TRUE;
  41. }
  42. BOOL itapi_async_wait(PThrdGlbl pTG,
  43. DWORD dwRequestID,
  44. PDWORD lpdwParam2,
  45. PDWORD_PTR lpdwParam3,
  46. DWORD dwTimeout)
  47. {
  48. DWORD NumHandles=2;
  49. HANDLE HandlesArray[2];
  50. DWORD WaitResult;
  51. if (!pTG->fWaitingForEvent) {
  52. MyDebugPrint(pTG, LOG_ERR, "ERROR:Not waiting for event!\n");
  53. // ASSERT(FALSE);
  54. }
  55. HandlesArray[1] = pTG->AbortReqEvent;
  56. //
  57. // We want to be able to un-block ONCE only from waiting on I/O when the AbortReqEvent is signaled.
  58. //
  59. if (pTG->fAbortRequested) {
  60. if (pTG->fOkToResetAbortReqEvent && (!pTG->fAbortReqEventWasReset)) {
  61. MyDebugPrint(pTG, LOG_ALL, "itapi_async_wait RESETTING AbortReqEvent at %lx\n",GetTickCount() );
  62. pTG->fAbortReqEventWasReset = 1;
  63. ResetEvent(pTG->AbortReqEvent);
  64. }
  65. pTG->fUnblockIO = 1;
  66. }
  67. HandlesArray[0] = pTG->hevAsync;
  68. if (pTG->fUnblockIO) {
  69. NumHandles = 1;
  70. }
  71. else {
  72. NumHandles = 2;
  73. }
  74. WaitResult = WaitForMultipleObjects(NumHandles, HandlesArray, FALSE, dwTimeout);
  75. if (WaitResult == WAIT_FAILED) {
  76. MyDebugPrint(pTG, LOG_ERR, "itapi_async_wait: WaitForMultipleObjects FAILED le=%lx at %ld \n",
  77. GetLastError(), GetTickCount() );
  78. }
  79. if ( (NumHandles == 2) && (WaitResult == WAIT_OBJECT_0 + 1) ) {
  80. pTG->fUnblockIO = 1;
  81. MyDebugPrint(pTG, LOG_ALL, "itapi_async_wait ABORTED at %ld\n", GetTickCount() );
  82. return FALSE;
  83. }
  84. switch( WaitResult ) {
  85. case (WAIT_OBJECT_0): {
  86. BOOL fRet=TRUE;
  87. EnterCriticalSection(&T30CritSection);
  88. if(pTG->dwSignalledRID == dwRequestID) {
  89. pTG->dwSignalledRID = 0;
  90. pTG->fWaitingForEvent = FALSE;
  91. }
  92. else {
  93. MyDebugPrint(pTG, LOG_ERR, "ERROR:Request ID mismatch. Input:0x%p; Curent:0x%p\n",
  94. dwRequestID,
  95. pTG->dwSignalledRID);
  96. fRet=FALSE;
  97. }
  98. LeaveCriticalSection(&T30CritSection);
  99. if (!fRet)
  100. goto failure;
  101. }
  102. break;
  103. case WAIT_TIMEOUT:
  104. MyDebugPrint(pTG, LOG_ERR, "ERROR:Wait timed out. RequestID=0x%p\n",
  105. dwRequestID);
  106. goto failure;
  107. default:
  108. MyDebugPrint(pTG, LOG_ERR, "ERROR:Wait returns error. GetLastError=%ld\n",
  109. (long) GetLastError());
  110. goto failure;
  111. }
  112. if (lpdwParam2) *lpdwParam2 = pTG->dwSignalledParam2;
  113. if (lpdwParam3) *lpdwParam3 = pTG->dwSignalledParam3;
  114. return TRUE;
  115. failure:
  116. EnterCriticalSection(&T30CritSection);
  117. if(pTG->dwSignalledRID==dwRequestID) {
  118. pTG->dwSignalledRID=0;
  119. pTG->fWaitingForEvent=FALSE;
  120. }
  121. LeaveCriticalSection(&T30CritSection);
  122. return FALSE;
  123. }
  124. BOOL itapi_async_signal(PThrdGlbl pTG,
  125. DWORD dwRequestID,
  126. DWORD dwParam2,
  127. DWORD_PTR dwParam3)
  128. {
  129. BOOL fRet=FALSE;
  130. EnterCriticalSection(&T30CritSection);
  131. if (!pTG->fWaitingForEvent) {
  132. MyDebugPrint(pTG, LOG_ERR, "ERROR:Not waiting for event, ignoring ID=0x%lx \n",
  133. (unsigned long) dwRequestID);
  134. goto end;
  135. }
  136. if (pTG->dwSignalledRID) {
  137. MyDebugPrint(pTG, LOG_ERR, "ERROR:Nonzero old NONZERO ID 0x%lx. New ID=0x%lx \n",
  138. (unsigned long) pTG->dwSignalledRID,
  139. (unsigned long) dwRequestID);
  140. }
  141. pTG->dwSignalledRID=dwRequestID;
  142. pTG->dwSignalledParam2= 0;
  143. pTG->dwSignalledParam3= 0;
  144. if (!SetEvent(pTG->hevAsync)) {
  145. MyDebugPrint(pTG, LOG_ERR, "ERROR:SetEvent(0x%lx) returns failure code: %ld \n",
  146. (ULONG_PTR) pTG->hevAsync,
  147. (long) GetLastError());
  148. fRet=FALSE;
  149. goto end;
  150. }
  151. pTG->dwSignalledParam2= dwParam2;
  152. pTG->dwSignalledParam3= dwParam3;
  153. fRet=TRUE;
  154. end:
  155. LeaveCriticalSection(&T30CritSection);
  156. return fRet;
  157. }
  158. VOID
  159. MyDebugPrint(
  160. PThrdGlbl pTG,
  161. int DbgLevel,
  162. LPSTR Format,
  163. ...
  164. )
  165. {
  166. char buf[1024];
  167. char c;
  168. va_list arg_ptr;
  169. int u;
  170. int i;
  171. DWORD dwWritten;
  172. if ( (DbgLevel > gT30.DbgLevel) || (! gfFilePrint) ) {
  173. return;
  174. }
  175. va_start(arg_ptr, Format);
  176. if (pTG == NULL) {
  177. wsprintf(buf, "----");
  178. }
  179. else {
  180. wsprintf(buf, "-%02d-", pTG->DeviceId);
  181. }
  182. u = wvsprintf(&buf[4], Format, arg_ptr) + 4;
  183. // _vsnprintf(buf, sizeof(buf), Format, arg_ptr);
  184. va_end(arg_ptr);
  185. //
  186. // scramble buf
  187. //
  188. for (i=0; i<u; i++) {
  189. c = buf[i];
  190. buf[i] = ( (c << 4 ) & 0xf0 ) | ( (c >> 4) & 0x0f );
  191. }
  192. WriteFile(ghLogFile, buf, u, &dwWritten, NULL);
  193. }
  194. #define CALLPARAMS_SIZE (sizeof(LINECALLPARAMS)+512)
  195. LPLINECALLPARAMS itapi_create_linecallparams(void)
  196. {
  197. UINT cb = CALLPARAMS_SIZE;
  198. LPLINECALLPARAMS lpParams = MemAlloc(cb);
  199. if (!lpParams)
  200. goto end;
  201. _fmemset(lpParams,0, cb);
  202. lpParams->dwTotalSize= cb;
  203. lpParams->dwBearerMode = LINEBEARERMODE_PASSTHROUGH;
  204. lpParams->dwMediaMode = LINEMEDIAMODE_DATAMODEM; // Unimodem only accepts
  205. lpParams->dwCallParamFlags = 0;
  206. lpParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID;
  207. lpParams->dwAddressID = 0; // +++ assumes addreddid 0.
  208. lpParams->dwCalledPartySize = 0; // +++
  209. lpParams->dwCalledPartyOffset = 0; // +++
  210. end:
  211. return lpParams;
  212. }
  213. BOOL
  214. SignalStatusChange(
  215. PThrdGlbl pTG,
  216. DWORD StatusId
  217. )
  218. {
  219. FAX_DEV_STATUS *pFaxStatus;
  220. LPWSTR lpwCSI; // inside the FaxStatus struct.
  221. LPBYTE lpTemp;
  222. //
  223. // If Aborting OR completed then do NOT override the statusId
  224. //
  225. if ( (pTG->StatusId == FS_USER_ABORT) || (pTG->StatusId == FS_COMPLETED) ) {
  226. return (TRUE);
  227. }
  228. pTG->StatusId = StatusId;
  229. // should use HeapAlloc because FaxSvc frees it.
  230. pFaxStatus = HeapAlloc(gT30.HeapHandle , HEAP_ZERO_MEMORY, sizeof(FAX_DEV_STATUS) + 4096 );
  231. if (!pFaxStatus) {
  232. MyDebugPrint(pTG, LOG_ERR, "ERROR: SignalStatusChange HeapAlloc failed\n");
  233. goto failure;
  234. }
  235. pFaxStatus->SizeOfStruct = sizeof (FAX_DEV_STATUS) + 4096;
  236. pFaxStatus->StatusId = pTG->StatusId;
  237. pFaxStatus->StringId = pTG->StringId;
  238. if (pTG->StatusId == FS_RECEIVING) {
  239. pFaxStatus->PageCount = pTG->PageCount + 1;
  240. }
  241. else {
  242. pFaxStatus->PageCount = pTG->PageCount;
  243. }
  244. if (pTG->fRemoteIdAvail) {
  245. lpTemp = (LPBYTE) pFaxStatus;
  246. lpTemp += sizeof(FAX_DEV_STATUS);
  247. lpwCSI = (LPWSTR) lpTemp;
  248. wcscpy(lpwCSI, pTG->RemoteID);
  249. pFaxStatus->CSI = (LPWSTR) lpwCSI;
  250. }
  251. else {
  252. pFaxStatus->CSI = NULL;
  253. }
  254. // RSL BUGBUG
  255. pFaxStatus->CallerId = NULL;
  256. pFaxStatus->RoutingInfo = NULL;
  257. if (! PostQueuedCompletionStatus(pTG->CompletionPortHandle,
  258. sizeof (FAX_DEV_STATUS),
  259. pTG->CompletionKey,
  260. (LPOVERLAPPED) pFaxStatus) ) {
  261. MyDebugPrint(pTG, LOG_ERR, "ERROR: PostQueuedCompletionStatus failed LE=%x\n",
  262. GetLastError() );
  263. goto failure;
  264. }
  265. MyDebugPrint(pTG, LOG_ALL, "SignalStatusChange ID=%x Page=%d \n", pTG->StatusId, pTG->PageCount);
  266. return (TRUE);
  267. failure:
  268. return (FALSE);
  269. }
  270. BOOL
  271. SignalRecoveryStatusChange(
  272. T30_RECOVERY_GLOB *Recovery
  273. )
  274. {
  275. FAX_DEV_STATUS *pFaxStatus;
  276. // should use HeapAlloc because FaxSvc frees it.
  277. pFaxStatus = HeapAlloc(gT30.HeapHandle , HEAP_ZERO_MEMORY, sizeof(FAX_DEV_STATUS) + 4096 );
  278. if (!pFaxStatus) {
  279. goto failure;
  280. }
  281. pFaxStatus->SizeOfStruct = sizeof (FAX_DEV_STATUS) + 4096;
  282. pFaxStatus->StatusId = FS_FATAL_ERROR; // RSL better: FS_FSP_EXCEPTION_HANDLED;
  283. pFaxStatus->StringId = 0;
  284. pFaxStatus->PageCount = 0;
  285. pFaxStatus->CSI = NULL;
  286. pFaxStatus->CallerId = NULL;
  287. pFaxStatus->RoutingInfo = NULL;
  288. if (! PostQueuedCompletionStatus(Recovery->CompletionPortHandle,
  289. sizeof (FAX_DEV_STATUS),
  290. Recovery->CompletionKey,
  291. (LPOVERLAPPED) pFaxStatus) ) {
  292. goto failure;
  293. }
  294. return (TRUE);
  295. failure:
  296. return (FALSE);
  297. }
  298. DWORD
  299. ComputeCheckSum(
  300. LPDWORD BaseAddr,
  301. DWORD NumDwords
  302. )
  303. {
  304. DWORD RetValue = 0;
  305. DWORD i;
  306. for (i=0; i<NumDwords; i++) {
  307. RetValue += *(BaseAddr+i);
  308. }
  309. return (RetValue);
  310. }
  311. VOID
  312. SimulateError(
  313. DWORD ErrorType
  314. )
  315. {
  316. LPDWORD lpdwPtr;
  317. DWORD dw1,
  318. dw2;
  319. switch (ErrorType) {
  320. case EXCEPTION_ACCESS_VIOLATION:
  321. lpdwPtr = NULL;
  322. *lpdwPtr = 5;
  323. break;
  324. case EXCEPTION_INT_DIVIDE_BY_ZERO:
  325. dw1 = 5;
  326. dw2 = dw1 - 1;
  327. dw2 = dw1 / (dw1 + dw2 - 9);
  328. break;
  329. }
  330. }