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.

975 lines
22 KiB

  1. /*******************************************************************/
  2. /* Copyright(c) 1992 Microsoft Corporation */
  3. /*******************************************************************/
  4. //***
  5. //
  6. // Filename: timehand.c
  7. //
  8. // Description: This module contains the procedures for the supervisor's
  9. // procedure-driven state machine that handles timer events.
  10. //
  11. // Author: Stefan Solomon (stefans) May 26, 1992.
  12. //
  13. //
  14. //***
  15. #include "ddm.h"
  16. #include "handlers.h"
  17. #include "timer.h"
  18. #include "objects.h"
  19. #include "util.h"
  20. #include "routerif.h"
  21. #include "rasapiif.h"
  22. #include <raserror.h>
  23. #include <serial.h>
  24. #include "rasmanif.h"
  25. #include <string.h>
  26. #include <stdlib.h>
  27. #include <memory.h>
  28. //
  29. // Defines a list of blocks of time.
  30. //
  31. // The time block is expressed as a pair as follows:
  32. // <offset from midnight sunday, length>
  33. //
  34. // For example, the block of time from 7:00a to 8:30a on Monday
  35. // would be
  36. // <24*60+7*60, 90> or <1860, 90>
  37. //
  38. //
  39. typedef struct _MPR_TIME_BLOCK
  40. {
  41. DWORD dwTime; // Time of day expressed as # of mins since 12:00a
  42. DWORD dwLen; // # of minutes in this time block
  43. } MPR_TIME_BLOCK;
  44. //
  45. // Amount by which resizable array grows in TbCreateList
  46. //
  47. #define TB_GROW 30
  48. #define TBDIGIT(_x) ((_x) - L'0')
  49. //
  50. // Local prototypes
  51. //
  52. PVOID
  53. TbAlloc(
  54. IN DWORD dwSize,
  55. IN BOOL bZero);
  56. VOID
  57. TbFree(
  58. IN PVOID pvData);
  59. DWORD
  60. TbCreateList(
  61. IN PWCHAR pszBlocks,
  62. OUT MPR_TIME_BLOCK** ppBlocks,
  63. OUT LPDWORD lpdwCount);
  64. DWORD
  65. TbCleanupList(
  66. IN MPR_TIME_BLOCK* pList);
  67. DWORD
  68. TbBlockFromString(
  69. IN PWCHAR pszBlock,
  70. IN DWORD dwDay,
  71. OUT MPR_TIME_BLOCK* pBlock);
  72. DWORD
  73. TbPrintBlock(
  74. IN MPR_TIME_BLOCK* pBlock);
  75. //
  76. // Common allocation for Tb* functions. Will zero
  77. // memory if bZero is set.
  78. //
  79. PVOID
  80. TbAlloc(
  81. IN DWORD dwSize,
  82. IN BOOL bZero)
  83. {
  84. return LOCAL_ALLOC(0, dwSize);
  85. }
  86. //
  87. // Common free for Tb* functions
  88. //
  89. VOID
  90. TbFree(
  91. IN PVOID pvData)
  92. {
  93. LOCAL_FREE(pvData);
  94. }
  95. //
  96. // Translates a multi-sz string containing time blocks into
  97. // a MPR_TIME_BLOCK_LIST
  98. //
  99. DWORD
  100. TbCreateList(
  101. IN PWCHAR pszBlocks,
  102. OUT MPR_TIME_BLOCK** ppBlocks,
  103. OUT LPDWORD lpdwCount)
  104. {
  105. DWORD dwErr = NO_ERROR, dwDay = 0, i = 0, dwTot = 0;
  106. MPR_TIME_BLOCK* pBlocks = NULL, *pTemp = NULL;
  107. PWCHAR pszCurBlock = NULL, pszStart, pszEnd;
  108. // Initailze
  109. //
  110. *ppBlocks = NULL;
  111. *lpdwCount = 0;
  112. pszCurBlock = pszBlocks;
  113. while (pszCurBlock && *pszCurBlock)
  114. {
  115. // Calculate the day indicated in the current block
  116. //
  117. // pszCurBlock = "d hh:mm-hh:mm hh:mm-hh:mm ..."
  118. //
  119. if (! iswdigit(*pszCurBlock))
  120. {
  121. dwErr = ERROR_INVALID_PARAMETER;
  122. break;
  123. }
  124. dwDay = *pszCurBlock - L'0';
  125. // Advance past the day portion of the line to the
  126. // timeblock portion
  127. //
  128. if (pszStart = wcsstr(pszCurBlock, L" "))
  129. {
  130. pszStart++;
  131. // Loop through the blocks in this line (separated by spaces).
  132. //
  133. // pszStart = "hh:mm-hh:mm hh:mm-hh:mm ..."
  134. //
  135. while (TRUE)
  136. {
  137. // Parse out the current time block
  138. // hh:mm-hh:mm
  139. //
  140. pszEnd = wcsstr(pszStart, L" ");
  141. if (pszEnd)
  142. {
  143. *pszEnd = L'\0';
  144. }
  145. // Resize the array if needed
  146. //
  147. if (i >= dwTot)
  148. {
  149. dwTot += TB_GROW;
  150. pTemp = (MPR_TIME_BLOCK*)
  151. TbAlloc(dwTot * sizeof(MPR_TIME_BLOCK), TRUE);
  152. if (pTemp == NULL)
  153. {
  154. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  155. break;
  156. }
  157. if (dwTot - TB_GROW != 0)
  158. {
  159. CopyMemory(
  160. pTemp,
  161. pBlocks,
  162. sizeof(MPR_TIME_BLOCK) * (dwTot - TB_GROW));
  163. }
  164. TbFree(pBlocks);
  165. pBlocks = pTemp;
  166. }
  167. // Generate the current time block
  168. //
  169. dwErr = TbBlockFromString(pszStart, dwDay, &pBlocks[i++]);
  170. if (dwErr != NO_ERROR)
  171. {
  172. break;
  173. }
  174. // Undo any changes made to the string and
  175. // advance to the next time block
  176. //
  177. if (pszEnd)
  178. {
  179. *pszEnd = L' ';
  180. pszStart = pszEnd + 1;
  181. }
  182. else
  183. {
  184. // Exit the loop successfully
  185. break;
  186. }
  187. }
  188. if (dwErr != NO_ERROR)
  189. {
  190. break;
  191. }
  192. }
  193. else
  194. {
  195. dwErr = ERROR_INVALID_PARAMETER;
  196. break;
  197. }
  198. // Increment the block of time in the multi-sz
  199. //
  200. pszCurBlock += wcslen(pszCurBlock) + 1;
  201. }
  202. // Cleanup
  203. {
  204. if (dwErr != NO_ERROR)
  205. {
  206. TbCleanupList(*ppBlocks);
  207. *ppBlocks = NULL;
  208. }
  209. else
  210. {
  211. *ppBlocks = pBlocks;
  212. *lpdwCount = i;
  213. }
  214. }
  215. return dwErr;
  216. }
  217. //
  218. // Cleans up the given series of time blocks.
  219. //
  220. DWORD
  221. TbCleanupList(
  222. IN MPR_TIME_BLOCK* pList)
  223. {
  224. TbFree(pList);
  225. return NO_ERROR;
  226. }
  227. //
  228. // Creates a time block based on a string which must
  229. // be in the form "hh:mm-hh:mm".
  230. //
  231. DWORD
  232. TbBlockFromString(
  233. IN PWCHAR pszBlock,
  234. IN DWORD dwDay,
  235. OUT MPR_TIME_BLOCK* pBlock)
  236. {
  237. DWORD dwErr = NO_ERROR, dwEndTime = 0;
  238. // Block must be in format:
  239. // "hh:mm-hh:mm"
  240. //
  241. if ((wcslen(pszBlock) != 11) ||
  242. (! iswdigit(pszBlock[0])) ||
  243. (! iswdigit(pszBlock[1])) ||
  244. (pszBlock[2] != L':') ||
  245. (! iswdigit(pszBlock[3])) ||
  246. (! iswdigit(pszBlock[4])) ||
  247. (pszBlock[5] != L'-') ||
  248. (! iswdigit(pszBlock[6])) ||
  249. (! iswdigit(pszBlock[7])) ||
  250. (pszBlock[8] != L':') ||
  251. (! iswdigit(pszBlock[9])) ||
  252. (! iswdigit(pszBlock[10]))
  253. )
  254. {
  255. return ERROR_INVALID_PARAMETER;
  256. }
  257. // Assign the time values to the block
  258. //
  259. pBlock->dwTime =
  260. (((TBDIGIT(pszBlock[0]) * 10) + TBDIGIT(pszBlock[1])) * 60) + // hrs
  261. ((TBDIGIT(pszBlock[3]) * 10) + TBDIGIT(pszBlock[4])) + // mns
  262. (dwDay * 24 * 60); // dys
  263. dwEndTime =
  264. (((TBDIGIT(pszBlock[6]) * 10) + TBDIGIT(pszBlock[7])) * 60) + // hrs
  265. ((TBDIGIT(pszBlock[9]) * 10) + TBDIGIT(pszBlock[10])) + // mns
  266. (dwDay * 24 * 60); // dys
  267. pBlock ->dwLen = dwEndTime - pBlock->dwTime;
  268. return dwErr;
  269. }
  270. //
  271. // Finds a time block that matches the given time.
  272. //
  273. // Parameters:
  274. // pList = list of time blocks to search
  275. // dwTime = time to search for (mins since midnight sunday)
  276. // ppBlock = the block that matched
  277. // pbFound = returned TRUE if dwTime lies within ppBlock.
  278. // returned FALSE if ppBlock is the next time block in pList
  279. // that occurs after dwTime.
  280. //
  281. DWORD
  282. TbSearchList(
  283. IN MPR_TIME_BLOCK* pList,
  284. IN DWORD dwCount,
  285. IN DWORD dwTime,
  286. OUT MPR_TIME_BLOCK** ppBlock,
  287. OUT PBOOL pbFound)
  288. {
  289. DWORD dwErr = NO_ERROR;
  290. DWORD i = 0;
  291. // Initialize
  292. //
  293. *pbFound = FALSE;
  294. *ppBlock = NULL;
  295. // Loop through the list looking for a block with
  296. // a time less than ours.
  297. //
  298. for (i = 0; (i < dwCount) && (dwTime >= pList[i].dwTime); i++);
  299. i--;
  300. // If we fall within the current block then we're
  301. // done.
  302. //
  303. if ((dwTime >= pList[i].dwTime) &&
  304. (dwTime - pList[i].dwTime <= pList[i].dwLen))
  305. {
  306. *pbFound = TRUE;
  307. *ppBlock = &pList[i];
  308. }
  309. // Otherwise, we don't fall within any block. Show the next block
  310. // that we qualify for (wrapping around as needed)
  311. //
  312. else
  313. {
  314. *pbFound = FALSE;
  315. *ppBlock = &pList[(i == dwCount-1) ? 0 : i+1];
  316. }
  317. return dwErr;
  318. }
  319. //
  320. // Traces a block for debugging purposes
  321. //
  322. DWORD
  323. TbTraceBlock(
  324. IN MPR_TIME_BLOCK* pBlock)
  325. {
  326. DWORD dwTime, dwDay;
  327. dwDay = pBlock->dwTime / (24*60);
  328. dwTime = pBlock->dwTime - (dwDay * (24*60));
  329. DDMTRACE5(
  330. "Time Block: %d, %02d:%02d-%02d:%02d\n",
  331. dwDay,
  332. dwTime / 60,
  333. dwTime % 60,
  334. (dwTime + pBlock->dwLen) / 60,
  335. (dwTime + pBlock->dwLen) % 60);
  336. return NO_ERROR;
  337. }
  338. //***
  339. //
  340. // Function: TimerHandler
  341. //
  342. // Descr:
  343. //
  344. //***
  345. VOID
  346. TimerHandler(
  347. VOID
  348. )
  349. {
  350. //
  351. // call our timer
  352. //
  353. TimerQTick();
  354. //
  355. // increment the system timer
  356. //
  357. gblDDMConfigInfo.dwSystemTime++;
  358. }
  359. //**
  360. //
  361. // Call: AnnouncePresenceHandler
  362. //
  363. // Returns: NO_ERROR - Success
  364. // Non-zero returns - Failure
  365. //
  366. // Description:
  367. //
  368. /*
  369. VOID
  370. AnnouncePresenceHandler(
  371. IN HANDLE hObject
  372. )
  373. {
  374. AnnouncePresence();
  375. TimerQInsert( NULL,
  376. gblDDMConfigInfo.dwAnnouncePresenceTimer,
  377. AnnouncePresenceHandler );
  378. }
  379. */
  380. //***
  381. //
  382. // Function: SvHwErrDelayCompleted
  383. //
  384. // Descr: Tries to repost a listen on the specified port.
  385. //
  386. //***
  387. VOID
  388. SvHwErrDelayCompleted(
  389. IN HANDLE hObject
  390. )
  391. {
  392. PDEVICE_OBJECT pDeviceObj;
  393. EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
  394. pDeviceObj = DeviceObjGetPointer( (HPORT)hObject );
  395. if ( pDeviceObj == NULL )
  396. {
  397. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  398. return;
  399. }
  400. if (pDeviceObj->DeviceState == DEV_OBJ_HW_FAILURE)
  401. {
  402. DDMTRACE1( "SvHwErrDelayCompleted: reposting listen for hPort%d\n",
  403. pDeviceObj->hPort);
  404. pDeviceObj->DeviceState = DEV_OBJ_LISTENING;
  405. RmListen(pDeviceObj);
  406. }
  407. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  408. }
  409. //***
  410. //
  411. // Function: SvCbDelayCompleted
  412. //
  413. // Descr: Tries to connect on the specified port.
  414. //
  415. //***
  416. VOID
  417. SvCbDelayCompleted(
  418. IN HANDLE hObject
  419. )
  420. {
  421. CHAR chCallbackNumber[MAX_PHONE_NUMBER_LEN+1];
  422. PDEVICE_OBJECT pDeviceObj;
  423. EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
  424. pDeviceObj = DeviceObjGetPointer( (HPORT)hObject );
  425. if ( pDeviceObj == NULL )
  426. {
  427. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  428. return;
  429. }
  430. WideCharToMultiByte( CP_ACP,
  431. 0,
  432. pDeviceObj->wchCallbackNumber,
  433. -1,
  434. chCallbackNumber,
  435. sizeof( chCallbackNumber ),
  436. NULL,
  437. NULL );
  438. DDMTRACE1( "SvCbDelayCmpleted:Entered, hPort=%d\n",pDeviceObj->hPort );
  439. if (pDeviceObj->DeviceState == DEV_OBJ_CALLBACK_DISCONNECTED)
  440. {
  441. pDeviceObj->DeviceState = DEV_OBJ_CALLBACK_CONNECTING;
  442. RmConnect(pDeviceObj, chCallbackNumber);
  443. }
  444. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  445. }
  446. //***
  447. //
  448. // Function: SvAuthTimeout
  449. //
  450. // Descr: Disconnects the remote client and stops the authentication
  451. //
  452. //
  453. VOID
  454. SvAuthTimeout(
  455. IN HANDLE hObject
  456. )
  457. {
  458. LPWSTR portnamep;
  459. PDEVICE_OBJECT pDeviceObj;
  460. EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
  461. pDeviceObj = DeviceObjGetPointer( (HPORT)hObject );
  462. if ( pDeviceObj == NULL )
  463. {
  464. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  465. return;
  466. }
  467. DDMTRACE1( "SvAuthTimeout: Entered, hPort=%d", pDeviceObj->hPort);
  468. portnamep = pDeviceObj->wchPortName;
  469. DDMLogWarning( ROUTERLOG_AUTH_TIMEOUT, 1, &portnamep );
  470. //
  471. // stop everything and go closing
  472. //
  473. DevStartClosing( pDeviceObj );
  474. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  475. }
  476. //***
  477. //
  478. // Function: SvDiscTimeout
  479. //
  480. // Descr: disconnects remote client if it has not done it itself
  481. //
  482. //
  483. VOID
  484. SvDiscTimeout(
  485. IN HANDLE hObject
  486. )
  487. {
  488. PDEVICE_OBJECT pDeviceObj;
  489. EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
  490. pDeviceObj = DeviceObjGetPointer( (HPORT)hObject );
  491. if ( pDeviceObj == NULL )
  492. {
  493. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  494. return;
  495. }
  496. DDMTRACE1( "SvDiscTimeout: Entered, hPort=%d", pDeviceObj->hPort );
  497. switch (pDeviceObj->DeviceState)
  498. {
  499. case DEV_OBJ_CALLBACK_DISCONNECTING:
  500. RmDisconnect(pDeviceObj);
  501. break;
  502. case DEV_OBJ_AUTH_IS_ACTIVE:
  503. DevStartClosing(pDeviceObj);
  504. break;
  505. default:
  506. break;
  507. }
  508. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  509. }
  510. //***
  511. //
  512. // Function: SvSecurityTimeout
  513. //
  514. // Descr: disconnects the connection because the 3rd party security DLL
  515. // did not complete in time.
  516. //
  517. //***
  518. VOID
  519. SvSecurityTimeout(
  520. IN HANDLE hObject
  521. )
  522. {
  523. LPWSTR portnamep;
  524. PDEVICE_OBJECT pDeviceObj;
  525. EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
  526. pDeviceObj = DeviceObjGetPointer( (HPORT)hObject );
  527. if ( pDeviceObj == NULL )
  528. {
  529. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  530. return;
  531. }
  532. DDMTRACE1( "SvSecurityTimeout: Entered,hPort=%d",pDeviceObj->hPort);
  533. portnamep = pDeviceObj->wchPortName;
  534. DDMLogWarning( ROUTERLOG_AUTH_TIMEOUT, 1, &portnamep );
  535. //
  536. // stop everything and go closing
  537. //
  538. DevStartClosing(pDeviceObj);
  539. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  540. }
  541. //***
  542. //
  543. // Function: ReConnectInterface
  544. //
  545. // Description: Will try to reconnect an interface.
  546. //
  547. //***
  548. VOID
  549. ReConnectInterface(
  550. IN HANDLE hObject
  551. )
  552. {
  553. ROUTER_INTERFACE_OBJECT * pIfObject;
  554. DWORD dwRetCode = NO_ERROR;
  555. EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
  556. EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  557. do
  558. {
  559. pIfObject = IfObjectGetPointer( hObject );
  560. if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL )
  561. {
  562. break;
  563. }
  564. if ( pIfObject->State != RISTATE_CONNECTING )
  565. {
  566. break;
  567. }
  568. dwRetCode = RasConnectionInitiate( pIfObject, TRUE );
  569. DDMTRACE2( "ReConnectInterface: To interface %ws returned %d",
  570. pIfObject->lpwsInterfaceName, dwRetCode );
  571. if ( dwRetCode != NO_ERROR )
  572. {
  573. IfObjectDisconnected( pIfObject );
  574. }
  575. }while( FALSE );
  576. LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  577. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  578. if ( dwRetCode != NO_ERROR )
  579. {
  580. LPWSTR lpwsAudit[1];
  581. lpwsAudit[0] = pIfObject->lpwsInterfaceName;
  582. DDMLogErrorString(ROUTERLOG_CONNECTION_FAILURE,1,lpwsAudit,dwRetCode,1);
  583. }
  584. }
  585. //***
  586. //
  587. // Function: MarkInterfaceAsReachable
  588. //
  589. // Description: Will mark an interface as reachable.
  590. //
  591. //***
  592. VOID
  593. MarkInterfaceAsReachable(
  594. IN HANDLE hObject
  595. )
  596. {
  597. ROUTER_INTERFACE_OBJECT * pIfObject;
  598. EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  599. do
  600. {
  601. pIfObject = IfObjectGetPointer( hObject );
  602. if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL )
  603. {
  604. break;
  605. }
  606. pIfObject->fFlags &= ~IFFLAG_CONNECTION_FAILURE;
  607. IfObjectNotifyOfReachabilityChange( pIfObject,
  608. TRUE,
  609. INTERFACE_CONNECTION_FAILURE );
  610. pIfObject->dwLastError = NO_ERROR;
  611. }while( FALSE );
  612. LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  613. }
  614. //**
  615. //
  616. // Call: ReConnectPersistentInterface
  617. //
  618. // Returns: None
  619. //
  620. // Description: Will insert an event in the timer Q that will reconnect this
  621. // interface.
  622. //
  623. VOID
  624. ReConnectPersistentInterface(
  625. IN HANDLE hObject
  626. )
  627. {
  628. ROUTER_INTERFACE_OBJECT * pIfObject;
  629. DWORD dwRetCode;
  630. EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  631. do
  632. {
  633. pIfObject = IfObjectGetPointer( hObject );
  634. if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL )
  635. {
  636. break;
  637. }
  638. if ( pIfObject->State != RISTATE_DISCONNECTED )
  639. {
  640. break;
  641. }
  642. dwRetCode = RasConnectionInitiate( pIfObject, FALSE );
  643. DDMTRACE2( "ReConnect to persistent interface %ws returned %d",
  644. pIfObject->lpwsInterfaceName, dwRetCode );
  645. }while( FALSE );
  646. LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  647. }
  648. //**
  649. //
  650. // Call: SetDialoutHoursRestriction
  651. //
  652. // Returns: NO_ERROR - Success
  653. // Non-zero returns - Failure
  654. //
  655. // Description:
  656. //
  657. VOID
  658. SetDialoutHoursRestriction(
  659. IN HANDLE hObject
  660. )
  661. {
  662. ROUTER_INTERFACE_OBJECT * pIfObject;
  663. SYSTEMTIME CurrentTime;
  664. MPR_TIME_BLOCK* pBlocks = NULL, *pTimeBlock = NULL;
  665. DWORD dwRetCode = NO_ERROR, dwCount, dwTime;
  666. DWORD dwTimer, dwBlDay;
  667. BOOL bFound = FALSE;
  668. EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  669. do
  670. {
  671. pIfObject = IfObjectGetPointer( hObject );
  672. if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL )
  673. {
  674. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  675. break;
  676. }
  677. //
  678. // Null dialout hours restriction is interpreted as
  679. // 'always allow'.
  680. //
  681. if (pIfObject->lpwsDialoutHoursRestriction == NULL)
  682. {
  683. pIfObject->fFlags &= ~IFFLAG_DIALOUT_HOURS_RESTRICTION;
  684. DDMTRACE("Dialout hours restriction off forever.");
  685. dwRetCode = NO_ERROR;
  686. break;
  687. }
  688. //
  689. // Generate the list of time blocks based on the current
  690. // multisz
  691. //
  692. dwRetCode = TbCreateList(
  693. pIfObject->lpwsDialoutHoursRestriction,
  694. &pBlocks,
  695. &dwCount);
  696. if (dwRetCode != NO_ERROR)
  697. {
  698. break;
  699. }
  700. //
  701. // If an empty list was created, then all hours were
  702. // specified as deny. Mark the interface unreachable
  703. // and set ourselves to wake up and check things later.
  704. //
  705. if ((dwCount == 0) || (pBlocks == NULL))
  706. {
  707. pIfObject->fFlags |= IFFLAG_DIALOUT_HOURS_RESTRICTION;
  708. DDMTRACE("Dialout hours restriction on forever.");
  709. dwRetCode = NO_ERROR;
  710. break;
  711. }
  712. //
  713. // Get the current time
  714. //
  715. GetLocalTime( &CurrentTime );
  716. //
  717. // Convert the current time into an offset in
  718. // minutes from midnight, sunday.
  719. //
  720. dwTime = (DWORD)
  721. ( ( CurrentTime.wDayOfWeek * 24 * 60 ) +
  722. ( CurrentTime.wHour * 60 ) +
  723. CurrentTime.wMinute );
  724. //
  725. // Search for the current time in the list of available times.
  726. //
  727. dwRetCode = TbSearchList(
  728. pBlocks,
  729. dwCount,
  730. dwTime,
  731. &pTimeBlock,
  732. &bFound);
  733. if (dwRetCode != NO_ERROR)
  734. {
  735. break;
  736. }
  737. //
  738. // If we fell within one of the blocks, set the timer
  739. // to go off after this block completes.
  740. //
  741. if (bFound)
  742. {
  743. dwTimer = ((pTimeBlock->dwTime + pTimeBlock->dwLen) - dwTime) + 1;
  744. pIfObject->fFlags &= ~IFFLAG_DIALOUT_HOURS_RESTRICTION;
  745. DDMTRACE1("Dialout hours restriction off for %d mins", dwTimer);
  746. TbTraceBlock(pTimeBlock);
  747. }
  748. //
  749. // If we didn't fall within one of the blocks, set the timer
  750. // to go off when the next block begins
  751. //
  752. else
  753. {
  754. //
  755. // Check for week wrap around (i.e. today is saturday, next
  756. // block is sunday).
  757. //
  758. dwBlDay = (pTimeBlock->dwTime / (24*60));
  759. //
  760. // If there's no week wrap around, calculation of timer
  761. // is trivial.
  762. //
  763. if ((DWORD)CurrentTime.wDayOfWeek <= dwBlDay)
  764. {
  765. dwTimer = pTimeBlock->dwTime - dwTime;
  766. }
  767. //
  768. // Otherwise, calculate the timer by adding one week to the
  769. // start of the next time block.
  770. //
  771. else
  772. {
  773. dwTimer = (pTimeBlock->dwTime + (7*24*60)) - dwTime;
  774. }
  775. pIfObject->fFlags |= IFFLAG_DIALOUT_HOURS_RESTRICTION;
  776. DDMTRACE1("Dialout hours restriction on for %d mins", dwTimer);
  777. TbTraceBlock(pTimeBlock);
  778. }
  779. //
  780. // Set the timer
  781. //
  782. TimerQInsert(
  783. pIfObject->hDIMInterface,
  784. dwTimer * 60,
  785. SetDialoutHoursRestriction );
  786. } while (FALSE);
  787. if (pIfObject)
  788. {
  789. if ( dwRetCode != NO_ERROR )
  790. {
  791. //
  792. // Do not set any restriction if the string is invalid
  793. //
  794. pIfObject->fFlags &= ~IFFLAG_DIALOUT_HOURS_RESTRICTION;
  795. }
  796. IfObjectNotifyOfReachabilityChange(
  797. pIfObject,
  798. !( pIfObject->fFlags & IFFLAG_DIALOUT_HOURS_RESTRICTION ),
  799. INTERFACE_DIALOUT_HOURS_RESTRICTION );
  800. }
  801. LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  802. // Cleanup
  803. if (pBlocks)
  804. {
  805. TbCleanupList(pBlocks);
  806. }
  807. }