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.

2124 lines
51 KiB

  1. //============================================================================
  2. // Copyright (c) 1996, Microsoft Corporation
  3. //
  4. // File: script.c
  5. //
  6. // History:
  7. // Abolade-Gbadegesin 03-29-96 Created.
  8. //
  9. // This file contains functions implementing the NT port
  10. // of Win9x dial-up scripting, listed in alphabetical order.
  11. //
  12. // See scriptp.h for details on the NT implementation.
  13. //============================================================================
  14. #include <scriptp.h>
  15. #include <lmwksta.h> // For NetWkstaUserGetInfo
  16. #include <lmapibuf.h> // For NetApiBufferFree
  17. //
  18. // Handle of module-instance for this DLL
  19. //
  20. HANDLE g_hinst;
  21. //
  22. // global critical section used to synhronize access to IP address strings
  23. //
  24. CRITICAL_SECTION g_cs;
  25. //
  26. // name of file to which script syntax errors are logged
  27. //
  28. CHAR c_szScriptLog[] = RASSCRIPT_LOG;
  29. //
  30. // event handle which would be notified in case of IPAddress Change
  31. //
  32. HANDLE hIpAddressSet = INVALID_HANDLE_VALUE;
  33. #define NET_SVCS_GROUP "-k netsvcs"
  34. //----------------------------------------------------------------------------
  35. // Function: DLLMAIN
  36. //
  37. // DLL entry-point for RASSCRIPT
  38. //----------------------------------------------------------------------------
  39. BOOL
  40. WINAPI
  41. RasScriptDllMain(
  42. IN HINSTANCE hinstance,
  43. IN DWORD dwReason,
  44. IN PVOID pUnused
  45. ) {
  46. BOOL bRetVal = TRUE;
  47. if (dwReason == DLL_PROCESS_ATTACH) {
  48. g_hinst = (HANDLE)hinstance;
  49. try
  50. {
  51. InitializeCriticalSection(&g_cs);
  52. }
  53. except (EXCEPTION_EXECUTE_HANDLER)
  54. {
  55. bRetVal = FALSE;
  56. }
  57. }
  58. else
  59. if (dwReason == DLL_PROCESS_DETACH) {
  60. DeleteCriticalSection(&g_cs);
  61. }
  62. return bRetVal;
  63. }
  64. //----------------------------------------------------------------------------
  65. // Function: RasScriptExecute
  66. //
  67. // Examines the given connection, and if there is a script for the connection,
  68. // executes the script to completion.
  69. // Returns the error code from script processing if a script is given,
  70. // and returns NO_ERROR otherwise.
  71. //----------------------------------------------------------------------------
  72. DWORD
  73. APIENTRY
  74. RasScriptExecute(
  75. IN HRASCONN hrasconn,
  76. IN PBENTRY* pEntry,
  77. IN CHAR* pszUserName,
  78. IN CHAR* pszPassword,
  79. OUT CHAR* pszIpAddress
  80. ) {
  81. DWORD dwErr;
  82. HANDLE hevent = NULL, hscript = NULL;
  83. HANDLE hEvents[2];
  84. RASSCRPT_TRACE("RasScriptExecute");
  85. do {
  86. //
  87. // create event on which to receive notification
  88. //
  89. hevent = CreateEvent(NULL, FALSE, FALSE, NULL);
  90. if (!hevent) {
  91. RASSCRPT_TRACE1("error %d creating event", dwErr = GetLastError());
  92. break;
  93. }
  94. // Create a separate event for SCRIPTCODE_IpAddressSet
  95. // event. We hit a timing window ow where we lose this
  96. // event (when we get a script complete event immediately
  97. // after a SCRIPTCODE_IpAddressSet event. bug 75226.
  98. hIpAddressSet = CreateEvent (NULL, FALSE, FALSE, NULL);
  99. if (!hIpAddressSet) {
  100. RASSCRPT_TRACE1("error %d creating event", dwErr = GetLastError());
  101. break;
  102. }
  103. //
  104. // initialize script processing
  105. //
  106. dwErr = RasScriptInit(
  107. hrasconn, pEntry, pszUserName, pszPassword, 0, hevent,
  108. &hscript
  109. );
  110. if (dwErr != NO_ERROR) {
  111. RASSCRPT_TRACE1("error %d initializing scripting", dwErr);
  112. break;
  113. }
  114. hEvents[0] = hevent;
  115. hEvents[1] = hIpAddressSet;
  116. //
  117. // loop waiting for script to finish running
  118. //
  119. for ( ; ; ) {
  120. dwErr = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
  121. if (dwErr - WAIT_OBJECT_0 == 0) {
  122. //
  123. // Retrieve the code for the event which occurred
  124. //
  125. DWORD dwCode = RasScriptGetEventCode(hscript);
  126. RASSCRPT_TRACE1("RasScriptExecute: eventcode %d", dwCode);
  127. //
  128. // Handle the event
  129. //
  130. if (dwCode == SCRIPTCODE_Done ||
  131. dwCode == SCRIPTCODE_Halted ||
  132. dwCode == SCRIPTCODE_HaltedOnError) {
  133. RASSCRPT_TRACE("script processing completed");
  134. dwErr = NO_ERROR;
  135. break;
  136. }
  137. }
  138. else
  139. if (dwErr - WAIT_OBJECT_0 == 1) {
  140. //
  141. // The IP address has been changed;
  142. // read the new IP address into the caller's buffer
  143. //
  144. RASSCRPT_TRACE("IP address changed");
  145. dwErr = RasScriptGetIpAddress(hscript, pszIpAddress);
  146. RASSCRPT_TRACE2("RasScriptGetIpAddress(e=%d,a=%s)",dwErr,pszIpAddress);
  147. }
  148. }
  149. } while(FALSE);
  150. if (hscript) { RasScriptTerm(hscript); }
  151. if (hevent) { CloseHandle(hevent); }
  152. if (hIpAddressSet) { CloseHandle (hIpAddressSet); }
  153. return dwErr;
  154. }
  155. //----------------------------------------------------------------------------
  156. // Function: RasScriptGetEventCode
  157. //
  158. // This function should be called to retrieve the event-code
  159. // when the scripting thread signals an event.
  160. // The event codes which may be returned are as follows:
  161. //
  162. // NO_ERROR: no code has been set
  163. // SCRIPTCODE_Done: the script has finished running;
  164. // the thread blocks until RasScriptTerm is called.
  165. // SCRIPTCODE_InputNotify: data is available in the buffer; if the buffer
  166. // is full, the thread blocks until
  167. // RasScriptReceive is called and the data
  168. // is read successfully.
  169. // SCRIPTCODE_KeyboardEnable: the keyboard should be enabled.
  170. // SCRIPTCODE_KeyboardDisable: the keyboard should be disabled.
  171. // SCRIPTCODE_IpAddressSet: the IP address has changed; the new address
  172. // can be retrieved via RasScriptGetIPAddress.
  173. // SCRIPTCODE_HaltedOnError: the script has halted due to an error.
  174. //----------------------------------------------------------------------------
  175. DWORD
  176. RasScriptGetEventCode(
  177. IN HANDLE hscript
  178. ) {
  179. SCRIPTCB* pscript = (SCRIPTCB *)hscript;
  180. RASSCRPT_TRACE("RasGetEventCode");
  181. if (!pscript) { return ERROR_INVALID_PARAMETER; }
  182. return pscript->dwEventCode;
  183. }
  184. //----------------------------------------------------------------------------
  185. // Function: RasScriptGetIpAddress
  186. //
  187. // This function retrieves the current IP address as set by the script.
  188. //----------------------------------------------------------------------------
  189. DWORD
  190. RasScriptGetIpAddress(
  191. IN HANDLE hscript,
  192. OUT CHAR* pszIpAddress
  193. ) {
  194. SCRIPTCB* pscript = (SCRIPTCB *)hscript;
  195. RASSCRPT_TRACE("RasGetIpAddress");
  196. if (!pscript || !pszIpAddress) { return ERROR_INVALID_PARAMETER; }
  197. //
  198. // Access to the IP address string must be synchronized
  199. // since it may also be accessed via RxSetIPAddress
  200. //
  201. EnterCriticalSection(&g_cs);
  202. if (pscript->pszIpAddress) {
  203. lstrcpy(pszIpAddress, pscript->pszIpAddress);
  204. }
  205. else {
  206. lstrcpy(pszIpAddress, "0.0.0.0");
  207. }
  208. LeaveCriticalSection(&g_cs);
  209. return NO_ERROR;
  210. }
  211. //----------------------------------------------------------------------------
  212. // Function: RasScriptInit
  213. //
  214. // Initializes for script processing on the given HRASCONN.
  215. //
  216. // This function creates a thread which handles script input and output
  217. // on the given connection's port.
  218. //
  219. // If there is no script for the connection, this function returns an error
  220. // unless the flag RASSCRIPT_NotifyOnInput is specified, in which case
  221. // the thread loops posting receive-data requests on the connection's port
  222. // until RasScriptTerm is called.
  223. //
  224. // If there is a script for the connection, the thread runs the script
  225. // to completion. If the flag RASSCRIPT_NotifyOnInput is specified,
  226. // the caller is notified when data is received on the port. The caller
  227. // can then retrieve the data by calling RasScriptReceive.
  228. //
  229. // Notification may be event-based or message-based. By default, notification
  230. // is event-based, and "Hnotifier" is treated as an event-handle.
  231. // The event is signalled to by the scripting thread, and the caller retrieves
  232. // the event code by calling RasScriptGetEventCode.
  233. //
  234. // Setting the flag RASSCRIPT_HwndNotify selects message-based notification,
  235. // and indicates that "Hnotifier" is an HWND. The WM_RASSCRIPT event is sent
  236. // to the window by the scripting thread, and "LParam" in the message sent
  237. // contains the event code. See RasScriptGetEventCode for descriptions
  238. // of the codes sent by the scripting thread.
  239. //----------------------------------------------------------------------------
  240. DWORD
  241. APIENTRY
  242. RasScriptInit(
  243. IN HRASCONN hrasconn,
  244. IN PBENTRY* pEntry,
  245. IN CHAR* pszUserName,
  246. IN CHAR* pszPassword,
  247. IN DWORD dwFlags,
  248. IN HANDLE hNotifier,
  249. OUT HANDLE* phscript
  250. ) {
  251. DWORD dwErr, dwSyntaxError = NO_ERROR;
  252. static const CHAR szSwitch[] = MXS_SWITCH_TXT;
  253. SCRIPTCB* pscript = NULL;
  254. #ifdef UNICODEUI
  255. //
  256. // Define structures to use depending on whether or not the RAS UI
  257. // is being built with Unicode.
  258. //
  259. #define PUISTR CHAR*
  260. #define PUIRCS RASCONNSTATUSA*
  261. #define PUIRC RASCREDENTIALSA*
  262. RASCONNSTATUSW rcs;
  263. WCHAR* pszSwitch = StrDupWFromA(MXS_SWITCH_TXT);
  264. #else
  265. #define PUISTR CHAR*
  266. #define PUIRCS RASCONNSTATUSA*
  267. #define PUIRC RASCREDENTIALSA*
  268. RASCONNSTATUSA rcs;
  269. CHAR* pszSwitch = szSwitch;
  270. #endif
  271. RASSCRPT_TRACE_INIT("RASSCRPT");
  272. RASSCRPT_TRACE("RasScriptInit");
  273. //
  274. // validate arguments
  275. //
  276. if (phscript) { *phscript = NULL; }
  277. if (!hrasconn ||
  278. !pEntry ||
  279. !pszUserName ||
  280. !pszPassword ||
  281. !hNotifier ||
  282. !phscript) {
  283. RASSCRPT_TRACE("RasScriptInit: required parameter not specified");
  284. #ifdef UNICODEUI
  285. Free(pszSwitch);
  286. #endif
  287. return ERROR_INVALID_PARAMETER;
  288. }
  289. //
  290. // initialize script processing
  291. //
  292. do {
  293. DWORD dwsize;
  294. DWORD dwthread;
  295. HANDLE hthread;
  296. //
  297. // Load required DLL function pointers.
  298. //
  299. dwErr = LoadRasapi32Dll();
  300. if (dwErr)
  301. break;
  302. dwErr = LoadRasmanDll();
  303. if (dwErr)
  304. break;
  305. //
  306. // Initialize RAS
  307. //
  308. dwErr = g_pRasInitialize();
  309. if ( dwErr )
  310. break;
  311. /*
  312. //
  313. // Connect to the local rasman server
  314. //
  315. dwErr = g_pRasRpcConnect ( NULL, NULL );
  316. if (dwErr)
  317. break; */
  318. //
  319. // allocate space for a control block
  320. //
  321. pscript = Malloc(sizeof(*pscript));
  322. if (!pscript) {
  323. dwErr = GetLastError();
  324. RASSCRPT_TRACE2("error %d allocating %d bytes", dwErr, sizeof(*pscript));
  325. break;
  326. }
  327. //
  328. // initialize the control block
  329. //
  330. ZeroMemory(pscript, sizeof(*pscript));
  331. //
  332. // copy the argument fields
  333. //
  334. pscript->hrasconn = hrasconn;
  335. pscript->pEntry = pEntry;
  336. pscript->dwFlags = dwFlags;
  337. pscript->hNotifier = hNotifier;
  338. pscript->hport = g_pRasGetHport(hrasconn);
  339. if (pscript->pEntry->pszIpAddress) {
  340. //
  341. // Copy the IP address for the entry
  342. //
  343. pscript->pszIpAddress =
  344. Malloc(lstrlenUI(pscript->pEntry->pszIpAddress) + 1);
  345. if (pscript->pszIpAddress) {
  346. StrCpyAFromUI(
  347. pscript->pszIpAddress, pscript->pEntry->pszIpAddress
  348. );
  349. }
  350. else {
  351. RASSCRPT_TRACE("error copying entry's IP address");
  352. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  353. break;
  354. }
  355. }
  356. //
  357. // Initialize our Win9x-compatible session-config-info structure
  358. //
  359. ZeroMemory(&pscript->sci, sizeof(pscript->sci));
  360. pscript->sci.dwSize = sizeof(pscript->sci);
  361. StrCpyAFromUI(pscript->sci.szEntryName, pEntry->pszEntryName);
  362. lstrcpy(pscript->sci.szUserName, pszUserName);
  363. lstrcpy(pscript->sci.szPassword, pszPassword);
  364. //
  365. // See if the user name is missing;
  366. // if so, read the currently-logged on user's name
  367. //
  368. if (!pscript->sci.szUserName[0]) {
  369. WKSTA_USER_INFO_1* pwkui1 = NULL;
  370. //
  371. // Not all params were specified, so read the dial-params
  372. // for this phonebook entry
  373. //
  374. dwErr = NetWkstaUserGetInfo(NULL, 1, (LPBYTE*)&pwkui1);
  375. RASSCRPT_TRACE2("NetWkstaUserGetInfo(e=%d,u=(%ls))", dwErr,
  376. (pwkui1) ? pwkui1->wkui1_username : L"null");
  377. if (dwErr == NO_ERROR && pwkui1 != NULL) {
  378. StrCpyAFromUI(pscript->sci.szUserName,
  379. (LPCWSTR)pwkui1->wkui1_username);
  380. NetApiBufferFree(pwkui1);
  381. }
  382. }
  383. //
  384. // See if there is a script for this connection's state;
  385. // if there is one then the device-type will be "switch"
  386. // and the device-name will be the script path
  387. //
  388. ZeroMemory(&rcs, sizeof(rcs));
  389. rcs.dwSize = sizeof(rcs);
  390. dwErr = g_pRasGetConnectStatus(hrasconn, (PUIRCS)&rcs);
  391. if (dwErr != NO_ERROR) {
  392. RASSCRPT_TRACE1("error %d getting connect status", dwErr);
  393. break;
  394. }
  395. //
  396. // Check the device-type (will be "switch" for scripted entries)
  397. // and the device name (will be a filename for scripted entries)
  398. //
  399. if (lstrcmpiUI(rcs.szDeviceType, pszSwitch) == 0 &&
  400. GetFileAttributesUI(rcs.szDeviceName) != 0xFFFFFFFF) {
  401. CHAR szDevice[RAS_MaxDeviceName + 1], *pszDevice = szDevice;
  402. StrCpyAFromUI(szDevice, rcs.szDeviceName);
  403. //
  404. // The device-type is "Switch" and the device-name
  405. // contains the name of an existing file;
  406. // initialize the SCRIPTDATA structure.
  407. //
  408. dwErr = RsInitData(pscript, pszDevice);
  409. //
  410. // If there was a syntax error in the script, we continue
  411. // with the initialization, but record the error code.
  412. // on any other error, we immediately terminate initialization.
  413. //
  414. if (dwErr == ERROR_SCRIPT_SYNTAX) {
  415. dwSyntaxError = dwErr;
  416. }
  417. else
  418. if (dwErr != NO_ERROR) { break; }
  419. }
  420. //
  421. // Initialize RASMAN fields, allocating buffers for RASMAN I/O
  422. //
  423. dwsize = SIZE_RecvBuffer;
  424. dwErr = g_pRasGetBuffer(&pscript->pRecvBuffer, &dwsize);
  425. RASSCRPT_TRACE2("RasGetBuffer:e=%d,s=%d", dwErr, dwsize);
  426. if (dwErr != NO_ERROR) {
  427. RASSCRPT_TRACE1("error %d allocating receive-buffer", dwErr);
  428. break;
  429. }
  430. dwsize = SIZE_SendBuffer;
  431. dwErr = g_pRasGetBuffer(&pscript->pSendBuffer, &dwsize);
  432. RASSCRPT_TRACE2("RasGetBuffer:e=%d,s=%d", dwErr, dwsize);
  433. if (dwErr != NO_ERROR) {
  434. RASSCRPT_TRACE1("error %d alloacting send-buffer", dwErr);
  435. break;
  436. }
  437. //
  438. // Create synchronization events used to control the background thread
  439. //
  440. pscript->hRecvRequest = CreateEvent(NULL, FALSE, FALSE, NULL);
  441. if (!pscript->hRecvRequest) {
  442. RASSCRPT_TRACE1("error %d creating receive-event", dwErr = GetLastError());
  443. break;
  444. }
  445. pscript->hRecvComplete = CreateEvent(NULL, FALSE, FALSE, NULL);
  446. if (!pscript->hRecvComplete) {
  447. RASSCRPT_TRACE1("error %d creating received-event", dwErr = GetLastError());
  448. break;
  449. }
  450. pscript->hStopRequest = CreateEvent(NULL, FALSE, FALSE, NULL);
  451. if (!pscript->hStopRequest) {
  452. RASSCRPT_TRACE1("error %d creating stop-event", dwErr = GetLastError());
  453. break;
  454. }
  455. pscript->hStopComplete = CreateEvent(NULL, FALSE, FALSE, NULL);
  456. if (!pscript->hStopComplete) {
  457. RASSCRPT_TRACE1("error %d creating stopped-event", dwErr = GetLastError());
  458. break;
  459. }
  460. //
  461. // Create the thread which will receive data and process the script
  462. //
  463. hthread = CreateThread(
  464. NULL, 0, RsThread, (PVOID)pscript, 0, &dwthread
  465. );
  466. if (!hthread) {
  467. RASSCRPT_TRACE1("error %d creating script-thread", dwErr = GetLastError());
  468. break;
  469. }
  470. CloseHandle(hthread);
  471. pscript->dwFlags |= RASSCRIPT_ThreadCreated;
  472. if ((VOID*)pszSwitch != (VOID*)szSwitch) { Free0(pszSwitch); }
  473. //
  474. // we've successfully initialized, return control to caller
  475. //
  476. *phscript = (HANDLE)pscript;
  477. //
  478. // if there was a syntax error in the script, return the special
  479. // error code (ERROR_SCRIPT_SYNTAX) to indicate the problem;
  480. // otherwise return NO_ERROR.
  481. //
  482. return (dwSyntaxError ? dwSyntaxError : NO_ERROR);
  483. } while(FALSE);
  484. //
  485. // an error occurred, so do cleanup
  486. //
  487. if ((VOID*)pszSwitch != (VOID*)szSwitch) { Free0(pszSwitch); }
  488. RasScriptTerm((HANDLE)pscript);
  489. return (dwErr ? dwErr : ERROR_UNKNOWN);
  490. }
  491. //----------------------------------------------------------------------------
  492. // Function: RasScriptReceive
  493. //
  494. // Called to retrieve the contents of the scripting thread's input buffer.
  495. // When this function completes successfully, if the input buffer was full
  496. // and the scripting thread was blocked, the thread continues executing.
  497. //
  498. // On input, "PdwBufferSize" should contain the size of "PBuffer", unless
  499. // "PBuffer" is NULL, in which case "*PdwBufferSize" is treated as 0.
  500. // On output, "PdwBufferSize" contains the size required to read
  501. // the input buffer, and if the return value is NO_ERROR, then "PBuffer"
  502. // contains the data in the input buffer. If the return value is
  503. // ERROR_INSUFFICIENT_BUFFER, "PBuffer" was not large enough.
  504. //----------------------------------------------------------------------------
  505. DWORD
  506. APIENTRY
  507. RasScriptReceive(
  508. IN HANDLE hscript,
  509. IN BYTE* pBuffer,
  510. IN OUT DWORD* pdwBufferSize
  511. ) {
  512. SCRIPTCB* pscript = (SCRIPTCB *)hscript;
  513. RASSCRPT_TRACE("RasScriptReceive");
  514. //
  515. // return if the caller didn't request input-notification
  516. // or if no buffer-size is available
  517. //
  518. if (!pscript || !pdwBufferSize ||
  519. !(pscript->dwFlags & RASSCRIPT_NotifyOnInput)) {
  520. return ERROR_INVALID_PARAMETER;
  521. }
  522. //
  523. // return if no buffer or if buffer too small
  524. //
  525. if (!pBuffer || *pdwBufferSize < pscript->dwRecvSize) {
  526. *pdwBufferSize = pscript->dwRecvSize;
  527. return ERROR_INSUFFICIENT_BUFFER;
  528. }
  529. //
  530. // copy the data, and notify the thread that the data has been read
  531. //
  532. CopyMemory(pBuffer, pscript->pRecvBuffer, pscript->dwRecvSize);
  533. *pdwBufferSize = pscript->dwRecvSize;
  534. SetEvent(pscript->hRecvComplete);
  535. return NO_ERROR;
  536. }
  537. //----------------------------------------------------------------------------
  538. // Function: RasScriptSend
  539. //
  540. // This function transmits bytes over the connection's port.
  541. //
  542. // "DwBufferSize" contains the number of bytes to insert from "PBuffer"
  543. //----------------------------------------------------------------------------
  544. DWORD
  545. APIENTRY
  546. RasScriptSend(
  547. IN HANDLE hscript,
  548. IN BYTE* pBuffer,
  549. IN DWORD dwBufferSize
  550. ) {
  551. DWORD dwsize;
  552. DWORD dwErr;
  553. SCRIPTCB *pscript = (SCRIPTCB *)hscript;
  554. RASSCRPT_TRACE("RasScriptSend");
  555. if (!pscript || !pBuffer || !dwBufferSize) {
  556. return ERROR_INVALID_PARAMETER;
  557. }
  558. //
  559. // send all the data in the buffer
  560. //
  561. for (dwsize = min(dwBufferSize, SIZE_SendBuffer);
  562. dwBufferSize;
  563. dwBufferSize -= dwsize, pBuffer += dwsize,
  564. dwsize = min(dwBufferSize, SIZE_SendBuffer)) {
  565. CopyMemory(pscript->pSendBuffer, pBuffer, dwsize);
  566. dwErr = g_pRasPortSend(
  567. pscript->hport, pscript->pSendBuffer, dwsize
  568. );
  569. RASSCRPT_TRACE1("g_pRasPortSend=%d", dwErr);
  570. DUMPB(pBuffer, dwsize);
  571. }
  572. return NO_ERROR;
  573. }
  574. //----------------------------------------------------------------------------
  575. // Function: RasScriptTerm
  576. //
  577. // This function terminates script processing, stopping the scripting thread.
  578. // The return code is the code from processing the script, and it may be
  579. //
  580. // NO_ERROR: the script had finished running, or the connection
  581. // had no script and the scripting thread was acting
  582. // in simple I/O mode.
  583. // ERROR_MORE_DATA: the script was still running.
  584. //----------------------------------------------------------------------------
  585. DWORD
  586. APIENTRY
  587. RasScriptTerm(
  588. IN HANDLE hscript
  589. ) {
  590. SCRIPTCB* pscript = hscript;
  591. RASSCRPT_TRACE("RasScriptTerm");
  592. if (!pscript) { return ERROR_INVALID_PARAMETER; }
  593. //
  594. // stop the thread if it is running
  595. //
  596. if (pscript->dwFlags & RASSCRIPT_ThreadCreated) {
  597. SetEvent(pscript->hStopRequest);
  598. WaitForSingleObject(pscript->hStopComplete, INFINITE);
  599. }
  600. if (pscript->pdata) { RsDestroyData(pscript); }
  601. if (pscript->hStopRequest) { CloseHandle(pscript->hStopRequest); }
  602. if (pscript->hStopComplete) { CloseHandle(pscript->hStopComplete); }
  603. if (pscript->hRecvRequest) { CloseHandle(pscript->hRecvRequest); }
  604. if (pscript->hRecvComplete) { CloseHandle(pscript->hRecvComplete); }
  605. if (pscript->pRecvBuffer) { g_pRasFreeBuffer(pscript->pRecvBuffer); }
  606. if (pscript->pSendBuffer) { g_pRasFreeBuffer(pscript->pSendBuffer); }
  607. Free0(pscript->pszIpAddress);
  608. Free(pscript);
  609. RASSCRPT_TRACE_TERM();
  610. return NO_ERROR;
  611. }
  612. //----------------------------------------------------------------------------
  613. // Function: RsDestroyData
  614. //
  615. // This function destroys the SCRIPTDATA portion of a SCRIPTCB.
  616. //----------------------------------------------------------------------------
  617. DWORD
  618. RsDestroyData(
  619. IN SCRIPTCB* pscript
  620. ) {
  621. SCRIPTDATA* pdata = pscript->pdata;
  622. if (!pdata) { return ERROR_INVALID_PARAMETER; }
  623. if (pdata->pmoduledecl) { Decl_Delete((PDECL)pdata->pmoduledecl); }
  624. if (pdata->pastexec) {
  625. Astexec_Destroy(pdata->pastexec); Free(pdata->pastexec);
  626. }
  627. if (pdata->pscanner) { Scanner_Destroy(pdata->pscanner); }
  628. return NO_ERROR;
  629. }
  630. //----------------------------------------------------------------------------
  631. // Function: RsInitData
  632. //
  633. // This function initializes the SCRIPTDATA portion of a SCRIPTCB,
  634. // preparing for script-processing.
  635. //----------------------------------------------------------------------------
  636. DWORD
  637. RsInitData(
  638. IN SCRIPTCB* pscript,
  639. IN LPCSTR pszScriptPath
  640. ) {
  641. RES res;
  642. DWORD dwErr = ERROR_SUCCESS;
  643. SCRIPTDATA *pdata;
  644. RASSCRPT_TRACE("RsInitData");
  645. do {
  646. //
  647. // allocate space for the SCRIPTDATA;
  648. //
  649. pscript->pdata = pdata = Malloc(sizeof(*pdata));
  650. if (!pdata) {
  651. RASSCRPT_TRACE1("error %d allocating SCRIPTDATA", dwErr = GetLastError());
  652. break;
  653. }
  654. //
  655. // initialize the structure
  656. //
  657. ZeroMemory(pdata, sizeof(*pdata));
  658. pdata->hscript = (HANDLE)pscript;
  659. lstrcpy(pdata->script.szPath, pszScriptPath);
  660. //
  661. // create a scanner and use it to open the script
  662. //
  663. res = Scanner_Create(&pdata->pscanner, &pscript->sci);
  664. if (RFAILED(res)) {
  665. RASSCRPT_TRACE1("failure %d creating scanner", res);
  666. break;
  667. }
  668. res = Scanner_OpenScript(pdata->pscanner, pszScriptPath);
  669. if (res == RES_E_FAIL || RFAILED(res)) {
  670. RASSCRPT_TRACE1("failure %d opening script", res);
  671. break;
  672. }
  673. //
  674. // allocate a script-execution handler
  675. //
  676. pdata->pastexec = Malloc(sizeof(*pdata->pastexec));
  677. if (!pdata->pastexec) {
  678. RASSCRPT_TRACE1("error %d allocating ASTEXEC", dwErr = GetLastError());
  679. break;
  680. }
  681. ZeroMemory(pdata->pastexec, sizeof(*pdata->pastexec));
  682. //
  683. // initialize the script-execution handler
  684. //
  685. res = Astexec_Init(
  686. pdata->pastexec, pscript, &pscript->sci,
  687. Scanner_GetStxerrHandle(pdata->pscanner)
  688. );
  689. if (!RSUCCEEDED(res)) {
  690. RASSCRPT_TRACE1("failure %d initializing ASTEXEC", res);
  691. break;
  692. }
  693. Astexec_SetHwnd(pdata->pastexec, (HWND)pdata);
  694. //
  695. // parse the script using the created scanner
  696. // and writing into the execution-handler's symbol-table
  697. //
  698. res = ModuleDecl_Parse(
  699. &pdata->pmoduledecl, pdata->pscanner,
  700. pdata->pastexec->pstSystem
  701. );
  702. if (RSUCCEEDED(res)) {
  703. //
  704. // generate code for the script
  705. //
  706. res = ModuleDecl_Codegen(pdata->pmoduledecl, pdata->pastexec);
  707. }
  708. //
  709. // see if anything went wrong
  710. //
  711. if (RFAILED(res)) {
  712. //
  713. // there was an error parsing the script.
  714. // we return the special error code ERROR_SCRIPT_SYNTAX
  715. // and log the errors to a file.
  716. //
  717. // This is not necessarily a fatal error, and so returning
  718. // the above error doesn't cause script-initialization to fail,
  719. // since if the user is in interactive mode, the connection
  720. // may be completed manually by typing into the terminal window.
  721. //
  722. // If we are not in interactive mode, this is a fatal error,
  723. // and RasScriptExecute handles the condition correctly
  724. // by terminating the script immediately
  725. //
  726. RASSCRPT_TRACE1("failure %d parsing script", res);
  727. RxLogErrors(
  728. (HANDLE)pscript, (VOID*)Scanner_GetStxerrHandle(pdata->pscanner)
  729. );
  730. Decl_Delete((PDECL)pdata->pmoduledecl);
  731. Astexec_Destroy(pdata->pastexec); Free(pdata->pastexec);
  732. Scanner_Destroy(pdata->pscanner);
  733. pscript->pdata = NULL;
  734. dwErr = ERROR_SCRIPT_SYNTAX;
  735. return dwErr;
  736. }
  737. //
  738. // all went well, return
  739. //
  740. return NO_ERROR;
  741. } while(FALSE);
  742. //
  743. // an error occurred, so do cleanup
  744. //
  745. if (pscript->pdata) { RsDestroyData(pscript); }
  746. return (dwErr ? dwErr : ERROR_UNKNOWN);
  747. }
  748. //----------------------------------------------------------------------------
  749. // Function: RsPostReceive
  750. //
  751. // Internal function:
  752. // posts receive-request to RASMAN
  753. //----------------------------------------------------------------------------
  754. DWORD
  755. RsPostReceive(
  756. IN SCRIPTCB* pscript
  757. ) {
  758. DWORD dwSize;
  759. DWORD dwErr;
  760. RASSCRPT_TRACE("RsPostReceive");
  761. dwSize = SIZE_RecvBuffer;
  762. dwErr = g_pRasPortReceive(
  763. pscript->hport, pscript->pRecvBuffer, &dwSize, SECS_RecvTimeout,
  764. pscript->hRecvRequest
  765. );
  766. RASSCRPT_TRACE2("RsPostReceive=%d,%d", dwErr, dwSize);
  767. return dwErr;
  768. }
  769. BOOL
  770. IsRasmanProcess()
  771. {
  772. CHAR *pszCmdLine = NULL;
  773. BOOL fRet = FALSE;
  774. pszCmdLine = GetCommandLineA();
  775. if( (NULL != pszCmdLine)
  776. && (strstr(pszCmdLine, NET_SVCS_GROUP)))
  777. {
  778. fRet = TRUE;
  779. }
  780. return fRet;
  781. }
  782. DWORD
  783. RsPostReceiveEx(
  784. IN SCRIPTCB* pscript
  785. ) {
  786. DWORD dwSize = 0;
  787. DWORD dwErr = ERROR_SUCCESS;
  788. RASSCRPT_TRACE("RsPostReceiveEx");
  789. if(IsRasmanProcess())
  790. {
  791. goto done;
  792. }
  793. RASSCRPT_TRACE("Calling RsPostReceiveEx");
  794. dwSize = SIZE_RecvBuffer;
  795. dwErr = g_pRasPortReceiveEx(
  796. pscript->hport,
  797. pscript->pRecvBuffer,
  798. &dwSize
  799. );
  800. done:
  801. RASSCRPT_TRACE2("RsPostReceiveEx=%d, %d",dwErr, dwSize );
  802. return dwErr;
  803. }
  804. //----------------------------------------------------------------------------
  805. // Function: RsSignal
  806. //
  807. // Internal function:
  808. // this is called to signal the notifier for a script, which may involve
  809. // setting an event or sending a message.
  810. //----------------------------------------------------------------------------
  811. VOID
  812. RsSignal(
  813. IN SCRIPTCB* pscript,
  814. IN DWORD dwEventCode
  815. ) {
  816. RASSCRPT_TRACE1("RsSignal: %d", dwEventCode);
  817. InterlockedExchange(&pscript->dwEventCode, dwEventCode);
  818. if (pscript->dwFlags & RASSCRIPT_HwndNotify) {
  819. SendNotifyMessage(
  820. (HWND)pscript->hNotifier, WM_RASAPICOMPLETE, 0, dwEventCode
  821. );
  822. }
  823. else {
  824. SetEvent(pscript->hNotifier);
  825. }
  826. }
  827. //----------------------------------------------------------------------------
  828. // Function: RsThread
  829. //
  830. // This function is the entry-point for the script processing thread.
  831. //
  832. // The scripting thread operates in a loop, posting receive requests
  833. // and receiving incoming data. If a script is associated with the port,
  834. // the thread also runs the script.
  835. //----------------------------------------------------------------------------
  836. DWORD
  837. RsThread(
  838. IN PVOID pParam
  839. ) {
  840. WORD wSize;
  841. #define POS_STOP 0
  842. #define POS_RECV 1
  843. #define POS_LAST 2
  844. BOOL bFirstRecv = TRUE;
  845. HANDLE hEvents[POS_LAST];
  846. SCRIPTCB* pscript = (SCRIPTCB *)pParam;
  847. SCRIPTDATA* pdata = pscript->pdata;
  848. DWORD dwErr, dwTicksBefore, dwTicksAfter, dwTicksElapsed;
  849. RASSCRPT_TRACE("RsThread");
  850. //
  851. // post receive-request to RASMAN
  852. //
  853. dwErr = RsPostReceive(pscript);
  854. if (dwErr != NO_ERROR && dwErr != PENDING) {
  855. RASSCRPT_TRACE1("error %d posting receive to RASMAN", dwErr);
  856. RsPostReceiveEx ( pscript );
  857. RsSignal(pscript, SCRIPTCODE_Halted);
  858. SetEvent(pscript->hStopComplete);
  859. return dwErr;
  860. }
  861. //
  862. // set up event array; we place the stop-request event first
  863. // in the array since the receive-event will be signalled more often
  864. // and placing it first might result in starvation
  865. // (waits are always satisfied by the first signalled object)
  866. //
  867. hEvents[POS_STOP] = pscript->hStopRequest;
  868. hEvents[POS_RECV] = pscript->hRecvRequest;
  869. if (pdata) { pdata->dwTimeout = INFINITE; }
  870. while (TRUE) {
  871. //
  872. // wait for receive to complete, for stop signal,
  873. // or for timeout to expire
  874. //
  875. // save the tick count so we can tell how long the wait lasted
  876. //
  877. dwTicksBefore = GetTickCount();
  878. dwErr = WaitForMultipleObjects(
  879. POS_LAST, hEvents, FALSE, pdata ? pdata->dwTimeout:INFINITE
  880. );
  881. dwTicksAfter = GetTickCount();
  882. //
  883. // see if the tick count wrapped around, and if so
  884. // adjust so we always get the correct elapsed time
  885. // from the expression (dwTicksAfter - dwTicksBefore)
  886. //
  887. if (dwTicksAfter < dwTicksBefore) {
  888. dwTicksAfter += MAXDWORD - dwTicksBefore;
  889. dwTicksBefore = 0;
  890. }
  891. dwTicksElapsed = dwTicksAfter - dwTicksBefore;
  892. RASSCRPT_TRACE1("RsThread: waited for %d milliseconds", dwTicksElapsed);
  893. //
  894. // if the timeout isn't INFINITE, decrement it by
  895. // the amount of time we've already waited
  896. //
  897. if (pdata && pdata->dwTimeout != INFINITE) {
  898. if (dwTicksElapsed >= pdata->dwTimeout) {
  899. pdata->dwTimeout = INFINITE;
  900. }
  901. else {
  902. pdata->dwTimeout -= dwTicksElapsed;
  903. }
  904. }
  905. //
  906. // Handle the return-code from WaitForMultipleObjects
  907. //
  908. if (dwErr == (WAIT_OBJECT_0 + POS_STOP)) {
  909. //
  910. // stop-request signalled, break
  911. //
  912. RASSCRPT_TRACE("RsThread: stop event signalled");
  913. RsSignal(pscript, SCRIPTCODE_Halted);
  914. break;
  915. }
  916. else
  917. if (dwErr == WAIT_TIMEOUT) {
  918. if (!pdata) { continue; }
  919. //
  920. // wait timed out, so that means we were blocked
  921. // on a "delay" or "waitfor ... until" statement;
  922. //
  923. Astexec_ClearPause(pdata->pastexec);
  924. //
  925. // if we blocked because of a "waitfor ... until",
  926. // finish processing the statement
  927. //
  928. if (Astexec_IsWaitUntil(pdata->pastexec)) {
  929. Astexec_SetStopWaiting(pdata->pastexec);
  930. Astexec_ClearWaitUntil(pdata->pastexec);
  931. }
  932. //
  933. // continue processing the script
  934. //
  935. if (RsThreadProcess(pscript) == ERROR_NO_MORE_ITEMS) {
  936. //
  937. // the script has stopped; if done, break;
  938. // otherwise, continue receiving data
  939. //
  940. if (pscript->dwEventCode == SCRIPTCODE_Done) {
  941. break;
  942. }
  943. else {
  944. //
  945. // Cleanup the script, but continue receiving data
  946. //
  947. RsDestroyData(pscript);
  948. pdata = pscript->pdata = NULL;
  949. }
  950. }
  951. }
  952. else
  953. if (dwErr == (WAIT_OBJECT_0 + POS_RECV)) {
  954. //
  955. // receive completed
  956. //
  957. RASMAN_INFO info;
  958. DWORD dwStart, dwRead;
  959. RASSCRPT_TRACE("RsThread: receive event signalled");
  960. //
  961. // Get the data received
  962. //
  963. dwErr = RsPostReceiveEx ( pscript );
  964. if ( NO_ERROR != dwErr
  965. && PENDING != dwErr )
  966. {
  967. RASSCRPT_TRACE1("error %d in RsPostReceiveEx", dwErr);
  968. RsSignal(pscript, SCRIPTCODE_Halted );
  969. break;
  970. }
  971. //
  972. // get the number of bytes received
  973. //
  974. dwErr = g_pRasGetInfo(NULL, pscript->hport, &info);
  975. if (dwErr != NO_ERROR) {
  976. RASSCRPT_TRACE1("error %d retrieving RASMAN_INFO", dwErr);
  977. RsSignal(pscript, SCRIPTCODE_Halted);
  978. break;
  979. }
  980. if( (info.RI_LastError != NO_ERROR)
  981. && (info.RI_ConnState != CONNECTING))
  982. {
  983. RASSCRPT_TRACE("Link dropped! port no longer in connecting state");
  984. RsSignal(pscript, SCRIPTCODE_Halted);
  985. break;
  986. }
  987. if (info.RI_LastError != NO_ERROR) {
  988. RASSCRPT_TRACE1("last error: %d", info.RI_LastError);
  989. continue;
  990. }
  991. RASSCRPT_TRACE1("RsThread: received %d bytes", info.RI_BytesReceived);
  992. //
  993. // on the first receive, we proceed even if there aren't any
  994. // characters read, since we need to run the first script commands
  995. //
  996. if (!bFirstRecv && info.RI_BytesReceived == 0) {
  997. //
  998. // something went wrong, post another receive request
  999. //
  1000. dwErr = RsPostReceive(pscript);
  1001. if ( dwErr != NO_ERROR
  1002. && dwErr != PENDING)
  1003. {
  1004. RASSCRPT_TRACE1("error %d in RsPostReceive", dwErr);
  1005. RsSignal(pscript, SCRIPTCODE_Halted);
  1006. break;
  1007. }
  1008. continue;
  1009. }
  1010. bFirstRecv = FALSE;
  1011. pscript->dwRecvSize = info.RI_BytesReceived;
  1012. pscript->dwRecvRead = 0;
  1013. DUMPB(pscript->pRecvBuffer, pscript->dwRecvSize);
  1014. //
  1015. // if the creator wants to know when data arrives,
  1016. // signal the creator's notification now;
  1017. // wait till the creator reads the data before proceeding
  1018. //
  1019. if (info.RI_BytesReceived &&
  1020. (pscript->dwFlags & RASSCRIPT_NotifyOnInput)) {
  1021. RsSignal(pscript, SCRIPTCODE_InputNotify);
  1022. WaitForSingleObject(pscript->hRecvComplete, INFINITE);
  1023. }
  1024. //
  1025. // if we have no script that's all we have to do,
  1026. // so just post another receive request and go back to waiting
  1027. //
  1028. if (!pdata) {
  1029. dwErr = RsPostReceive(pscript);
  1030. if ( dwErr != NO_ERROR
  1031. && dwErr != PENDING )
  1032. {
  1033. RASSCRPT_TRACE1("error %d in RsPostReceive",dwErr);
  1034. RsSignal(pscript, SCRIPTCODE_Halted);
  1035. break;
  1036. }
  1037. continue;
  1038. }
  1039. //
  1040. // read the data into the script's circular buffer
  1041. //
  1042. ReadIntoBuffer(pdata, &dwStart, &dwRead);
  1043. //
  1044. // do more script processing
  1045. //
  1046. if (RsThreadProcess(pscript) == ERROR_NO_MORE_ITEMS) {
  1047. //
  1048. // the script has stopped; if done, break;
  1049. // otherwise, continue receiving data
  1050. //
  1051. if (pscript->dwEventCode == SCRIPTCODE_Done) {
  1052. break;
  1053. }
  1054. else {
  1055. //
  1056. // Cleanup the script, but continue receiving data
  1057. //
  1058. RsDestroyData(pscript);
  1059. pdata = pscript->pdata = NULL;
  1060. }
  1061. }
  1062. }
  1063. }
  1064. //
  1065. // cancel any pending receives
  1066. //
  1067. g_pRasPortCancelReceive(pscript->hport);
  1068. SetEvent(pscript->hStopComplete);
  1069. RASSCRPT_TRACE("RsThread done");
  1070. return NO_ERROR;
  1071. }
  1072. //----------------------------------------------------------------------------
  1073. // Function: RsThreadProcess
  1074. //
  1075. // Called to process the script until it is blocked
  1076. // by a "waitfor" statement or a "delay" statement.
  1077. //----------------------------------------------------------------------------
  1078. DWORD
  1079. RsThreadProcess(
  1080. IN SCRIPTCB* pscript
  1081. ) {
  1082. RES res;
  1083. DWORD dwErr;
  1084. SCRIPTDATA *pdata = pscript->pdata;
  1085. RASSCRPT_TRACE("RsThreadProcess");
  1086. //
  1087. // now step through the script until we are blocked
  1088. // by a "delay" statement or a "waitfor" statement
  1089. //
  1090. dwErr = NO_ERROR;
  1091. do {
  1092. //
  1093. // break if its time to stop
  1094. //
  1095. if (WaitForSingleObject(pscript->hStopRequest, 0) == WAIT_OBJECT_0) {
  1096. SetEvent(pscript->hStopRequest);
  1097. break;
  1098. }
  1099. //
  1100. // process next command
  1101. //
  1102. res = Astexec_Next(pdata->pastexec);
  1103. // if (res != RES_OK) { break; }
  1104. //
  1105. // examine the resulting state
  1106. //
  1107. if (Astexec_IsDone(pdata->pastexec) ||
  1108. Astexec_IsHalted(pdata->pastexec)) {
  1109. //
  1110. // the script has come to an end, so set our stop event
  1111. // and break out of this loop
  1112. //
  1113. RASSCRPT_TRACE("RsThreadProcess: script completed");
  1114. //
  1115. // do stop-completion notification
  1116. //
  1117. if (Astexec_IsDone(pdata->pastexec)) {
  1118. RsSignal(pscript, SCRIPTCODE_Done);
  1119. }
  1120. else
  1121. if (!RFAILED(res)) {
  1122. RsSignal(pscript, SCRIPTCODE_Halted);
  1123. }
  1124. else {
  1125. RsSignal(pscript, SCRIPTCODE_HaltedOnError);
  1126. }
  1127. dwErr = ERROR_NO_MORE_ITEMS;
  1128. break;
  1129. }
  1130. else
  1131. if (Astexec_IsReadPending(pdata->pastexec)) {
  1132. //
  1133. // we're blocked waiting for input,
  1134. // so post another receive request and go back
  1135. // to waiting for data;
  1136. // if we're blocked on a "waitfor ... until"
  1137. // then the timeout will be in pdata->dwTimeout,
  1138. // otherwise pdata->dwTimeout will be INFINITE
  1139. // which is exactly how long we'll be waiting
  1140. //
  1141. RsPostReceive(pscript);
  1142. RASSCRPT_TRACE("RsThreadProcess: script waiting for input");
  1143. break;
  1144. }
  1145. else
  1146. if (Astexec_IsPaused(pdata->pastexec)) {
  1147. //
  1148. // we're blocked with a timeout, so pick up
  1149. // the timeout value from pdata->dwTimeout.
  1150. // we don't want to listen for input
  1151. // while we're blocked, so we don't post another receive-request
  1152. //
  1153. RASSCRPT_TRACE("RsThreadProcess: script paused");
  1154. break;
  1155. }
  1156. } while (TRUE);
  1157. return dwErr;
  1158. }
  1159. //----------------------------------------------------------------------------
  1160. // Function: RxLogErrors
  1161. //
  1162. // Logs script syntax errors to a file named %windir%\system32\ras\script.log
  1163. //----------------------------------------------------------------------------
  1164. DWORD
  1165. RxLogErrors(
  1166. IN HANDLE hscript,
  1167. IN HSA hsaStxerr
  1168. ) {
  1169. HANDLE hfile;
  1170. CHAR *pszPath;
  1171. STXERR stxerr;
  1172. SCRIPTDATA *pdata;
  1173. SCRIPTCB *pscript = hscript;
  1174. DWORD i, cel, dwErr, dwSize;
  1175. RASSCRPT_TRACE("RxLogErrors");
  1176. if (!pscript || !pscript->pdata) { return ERROR_INVALID_PARAMETER; }
  1177. pdata = pscript->pdata;
  1178. //
  1179. // get the pathname for the logfile
  1180. //
  1181. dwSize = ExpandEnvironmentStrings(c_szScriptLog, NULL, 0);
  1182. pszPath = Malloc((dwSize + 1) * sizeof(CHAR));
  1183. if (!pszPath) { return ERROR_NOT_ENOUGH_MEMORY; }
  1184. ExpandEnvironmentStrings(c_szScriptLog, pszPath, dwSize);
  1185. //
  1186. // create the file, overwriting it if it already exists
  1187. //
  1188. hfile = CreateFile(
  1189. pszPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
  1190. FILE_ATTRIBUTE_NORMAL, NULL
  1191. );
  1192. Free(pszPath);
  1193. if (INVALID_HANDLE_VALUE == hfile) {
  1194. dwErr = GetLastError();
  1195. RASSCRPT_TRACE1("error %d creating logfile", dwErr);
  1196. return dwErr;
  1197. }
  1198. //
  1199. // truncate the previous contents of the file, if any
  1200. //
  1201. SetFilePointer(hfile, 0, 0, FILE_BEGIN);
  1202. SetEndOfFile(hfile);
  1203. //
  1204. // get the number of syntax errors
  1205. //
  1206. cel = SAGetCount(hsaStxerr);
  1207. //
  1208. // append each error to the file
  1209. //
  1210. for (i = 0; i < cel; i++) {
  1211. UINT ids;
  1212. CHAR* pszErr;
  1213. BOOL bRet = SAGetItem(hsaStxerr, i, &stxerr);
  1214. if (!bRet) { continue; }
  1215. ids = IdsFromRes(Stxerr_GetRes(&stxerr));
  1216. if (ids == 0) { continue; }
  1217. //
  1218. // format the error message
  1219. //
  1220. ConstructMessage(
  1221. &pszErr, g_hinst, MAKEINTRESOURCE(ids), pdata->script.szPath,
  1222. Stxerr_GetLine(&stxerr), Stxerr_GetLexeme(&stxerr)
  1223. );
  1224. if (!pszErr) { continue; }
  1225. //
  1226. // write the message to the log file
  1227. //
  1228. dwSize = lstrlen(pszErr);
  1229. WriteFile(hfile, pszErr, lstrlen(pszErr), &dwSize, NULL);
  1230. WriteFile(hfile, "\r\n", 2, &dwSize, NULL);
  1231. //
  1232. // free the message pointer
  1233. //
  1234. GFree(pszErr);
  1235. }
  1236. CloseHandle(hfile);
  1237. return 0;
  1238. }
  1239. //----------------------------------------------------------------------------
  1240. // Function: RxReadFile
  1241. //
  1242. // Transfers data out of a RASMAN buffer into the circular buffer used
  1243. // by the Win9x scripting code
  1244. //----------------------------------------------------------------------------
  1245. BOOL
  1246. RxReadFile(
  1247. IN HANDLE hscript,
  1248. IN BYTE* pBuffer,
  1249. IN DWORD dwBufferSize,
  1250. OUT DWORD* pdwBytesRead
  1251. ) {
  1252. SCRIPTCB* pscript = (SCRIPTCB*)hscript;
  1253. DWORD dwRecvSize = pscript->dwRecvSize - pscript->dwRecvRead;
  1254. RASSCRPT_TRACE("RxReadFile");
  1255. if (!pdwBytesRead) { return FALSE; }
  1256. *pdwBytesRead = 0;
  1257. if ((INT)dwRecvSize <= 0) { return FALSE; }
  1258. if (!dwBufferSize) { return FALSE; }
  1259. *pdwBytesRead = min(dwBufferSize, dwRecvSize);
  1260. CopyMemory(
  1261. pBuffer, pscript->pRecvBuffer + pscript->dwRecvRead, *pdwBytesRead
  1262. );
  1263. pscript->dwRecvRead += *pdwBytesRead;
  1264. RASSCRPT_TRACE2("RxReadFile(rr=%d,br=%d)",pscript->dwRecvRead,*pdwBytesRead);
  1265. return TRUE;
  1266. }
  1267. //----------------------------------------------------------------------------
  1268. // Function: RxSetIPAddress
  1269. //
  1270. // Sets the IP address for the script's RAS entry
  1271. //----------------------------------------------------------------------------
  1272. DWORD
  1273. RxSetIPAddress(
  1274. IN HANDLE hscript,
  1275. IN LPCSTR lpszAddress
  1276. ) {
  1277. DWORD dwErr = NO_ERROR;
  1278. SCRIPTCB *pscript = (SCRIPTCB *)hscript;
  1279. RASSCRPT_TRACE1("RxSetIPAddress: %s", lpszAddress);
  1280. EnterCriticalSection(&g_cs);
  1281. //
  1282. // Free the existing IP address, if any
  1283. //
  1284. Free0(pscript->pszIpAddress);
  1285. //
  1286. // Allocate space for a copy of the address
  1287. //
  1288. pscript->pszIpAddress = Malloc(lstrlen(lpszAddress) + 1);
  1289. if (!pscript->pszIpAddress) { dwErr = ERROR_NOT_ENOUGH_MEMORY; }
  1290. else {
  1291. //
  1292. // Copy the new IP address
  1293. //
  1294. lstrcpy(pscript->pszIpAddress, lpszAddress);
  1295. }
  1296. LeaveCriticalSection(&g_cs);
  1297. //
  1298. // If successful, signal the caller that the IP address has changed
  1299. //
  1300. if (dwErr != NO_ERROR) {
  1301. RASSCRPT_TRACE1("error %d writing phonebook file", dwErr);
  1302. }
  1303. else {
  1304. if ( INVALID_HANDLE_VALUE != hIpAddressSet
  1305. && !(pscript->dwFlags & RASSCRIPT_HwndNotify))
  1306. {
  1307. DWORD dwEventCode = SCRIPTCODE_IpAddressSet;
  1308. RASSCRPT_TRACE1("RxSetIPAddress: %d", dwEventCode);
  1309. InterlockedExchange(&pscript->dwEventCode, dwEventCode);
  1310. SetEvent (hIpAddressSet);
  1311. }
  1312. else if (pscript->dwFlags & RASSCRIPT_HwndNotify)
  1313. RsSignal(pscript, SCRIPTCODE_IpAddressSet);
  1314. }
  1315. return dwErr;
  1316. }
  1317. //----------------------------------------------------------------------------
  1318. // Function: RxSetKeyboard
  1319. //
  1320. // Signals the script-owner to enable or disable keyboard input.
  1321. //----------------------------------------------------------------------------
  1322. DWORD
  1323. RxSetKeyboard(
  1324. IN HANDLE hscript,
  1325. IN BOOL bEnable
  1326. ) {
  1327. RASSCRPT_TRACE("RxSetKeyboard");
  1328. RsSignal(
  1329. (SCRIPTCB *)hscript,
  1330. bEnable ? SCRIPTCODE_KeyboardEnable : SCRIPTCODE_KeyboardDisable
  1331. );
  1332. return NO_ERROR;
  1333. }
  1334. //----------------------------------------------------------------------------
  1335. // Function: RxSendCreds
  1336. //
  1337. // Sends users password over the wire.
  1338. //----------------------------------------------------------------------------
  1339. DWORD
  1340. RxSendCreds(
  1341. IN HANDLE hscript,
  1342. IN CHAR controlchar
  1343. ) {
  1344. SCRIPTCB *pscript = (SCRIPTCB *) hscript;
  1345. DWORD dwErr;
  1346. RASSCRPT_TRACE("RasSendCreds");
  1347. dwErr = RasSendCreds(pscript->hport, controlchar);
  1348. RASSCRPT_TRACE1("RasSendCreds done. 0x%x", dwErr);
  1349. return (dwErr == NO_ERROR) ? RES_OK : RES_E_FAIL;
  1350. }
  1351. //----------------------------------------------------------------------------
  1352. // Function: RxSetPortData
  1353. //
  1354. // Changes settings for the COM port.
  1355. //----------------------------------------------------------------------------
  1356. DWORD
  1357. RxSetPortData(
  1358. IN HANDLE hscript,
  1359. IN VOID* pStatement
  1360. ) {
  1361. RES res;
  1362. STMT* pstmt;
  1363. RAS_PARAMS* pparam;
  1364. DWORD dwErr, dwFlags;
  1365. RASMAN_PORTINFO *prmpi;
  1366. SCRIPTCB *pscript = (SCRIPTCB *)hscript;
  1367. BYTE aBuffer[sizeof(RASMAN_PORTINFO) + sizeof(RAS_PARAMS) * 2];
  1368. RASSCRPT_TRACE("RxSetPortData");
  1369. //
  1370. // Retrieve the 'set port' statement
  1371. //
  1372. pstmt = (STMT*)pStatement;
  1373. dwFlags = SetPortStmt_GetFlags(pstmt);
  1374. //
  1375. // Set up the RASMAN_PORTINFO to be passed to RasPortSetInfo
  1376. //
  1377. prmpi = (RASMAN_PORTINFO*)aBuffer;
  1378. prmpi->PI_NumOfParams = 0;
  1379. pparam = prmpi->PI_Params;
  1380. //
  1381. // Collect the changes into the port-info structure
  1382. //
  1383. if (IsFlagSet(dwFlags, SPF_DATABITS)) {
  1384. lstrcpyA(pparam->P_Key, SER_DATABITS_KEY);
  1385. pparam->P_Type = Number;
  1386. pparam->P_Attributes = 0;
  1387. pparam->P_Value.Number = SetPortStmt_GetDatabits(pstmt);
  1388. RASSCRPT_TRACE1("GetDatabits==%d", pparam->P_Value.Number);
  1389. ++prmpi->PI_NumOfParams;
  1390. ++pparam;
  1391. }
  1392. if (IsFlagSet(dwFlags, SPF_STOPBITS)) {
  1393. lstrcpyA(pparam->P_Key, SER_STOPBITS_KEY);
  1394. pparam->P_Type = Number;
  1395. pparam->P_Attributes = 0;
  1396. pparam->P_Value.Number = SetPortStmt_GetStopbits(pstmt);
  1397. //
  1398. // The only 'stopbits' settings supported are 1 and 2;
  1399. // in order to set stopbits of 1, we need to pass 0
  1400. // to RasPortSetInfo, so the value is adjusted here.
  1401. //
  1402. if (pparam->P_Value.Number == 1) { --pparam->P_Value.Number; }
  1403. RASSCRPT_TRACE1("GetStopbits==%d", pparam->P_Value.Number);
  1404. ++prmpi->PI_NumOfParams;
  1405. ++pparam;
  1406. }
  1407. if (IsFlagSet(dwFlags, SPF_PARITY)) {
  1408. lstrcpyA(pparam->P_Key, SER_PARITY_KEY);
  1409. pparam->P_Type = Number;
  1410. pparam->P_Attributes = 0;
  1411. pparam->P_Value.Number = SetPortStmt_GetParity(pstmt);
  1412. RASSCRPT_TRACE1("GetParity==%d", pparam->P_Value.Number);
  1413. ++prmpi->PI_NumOfParams;
  1414. ++pparam;
  1415. }
  1416. //
  1417. // Send the changes down to RASMAN
  1418. //
  1419. if (!prmpi->PI_NumOfParams) { dwErr = NO_ERROR; }
  1420. else {
  1421. dwErr = g_pRasPortSetInfo(pscript->hport, prmpi);
  1422. RASSCRPT_TRACE1("g_pRasPortSetInfo==%d", dwErr);
  1423. if (dwErr != NO_ERROR) {
  1424. Stxerr_Add(
  1425. pscript->pdata->pastexec->hsaStxerr, "set port",
  1426. Ast_GetLine(pstmt), RES_E_FAIL
  1427. );
  1428. }
  1429. }
  1430. return (dwErr == NO_ERROR) ? RES_OK : RES_E_FAIL;
  1431. }
  1432. //----------------------------------------------------------------------------
  1433. // Function: RxWriteFile
  1434. //
  1435. // Transmits the given buffer thru RASMAN on a port
  1436. //----------------------------------------------------------------------------
  1437. VOID
  1438. RxWriteFile(
  1439. IN HANDLE hscript,
  1440. IN BYTE* pBuffer,
  1441. IN DWORD dwBufferSize,
  1442. OUT DWORD* pdwBytesWritten
  1443. ) {
  1444. RASSCRPT_TRACE("RxWriteFile");
  1445. if (!pdwBytesWritten) { return; }
  1446. RasScriptSend(hscript, pBuffer, dwBufferSize);
  1447. *pdwBytesWritten = dwBufferSize;
  1448. RASSCRPT_TRACE1("RxWriteFile(bw=%d)", *pdwBytesWritten);
  1449. }