Leaked source code of windows server 2003
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.

969 lines
34 KiB

  1. //depot/Lab03_N/Net/rras/ndis/raspptp/nt/thread.c#6 - edit change 19457 (text)
  2. /*******************************************************************
  3. *
  4. * Copyright (c) 1998-1999 Microsoft Corporation
  5. *
  6. * DESCRIPTION: THREAD.C - Thread handling routines, for NT
  7. * Also implements work items.
  8. *
  9. * AUTHOR: Stan Adermann (StanA)
  10. *
  11. * DATE:10/20/1998
  12. *
  13. *******************************************************************/
  14. #include "raspptp.h"
  15. #include <stdarg.h>
  16. #include <stdio.h>
  17. extern struct PPTP_ADAPTER * pgAdapter;
  18. //ULONG ProcCountTxQ[2] = {0, 0};
  19. //ULONG ProcCountRxQ[2] = {0, 0};
  20. HANDLE hPassiveThread = NULL;
  21. KEVENT EventPassiveThread;
  22. KEVENT EventKillThread;
  23. LIST_ENTRY WorkItemList;
  24. NDIS_SPIN_LOCK GlobalThreadLock;
  25. BOOLEAN ThreadingInitialized = FALSE;
  26. NDIS_STATUS
  27. ScheduleWorkItem(
  28. WORK_PROC Callback,
  29. PVOID Context,
  30. PVOID InfoBuf,
  31. ULONG InfoBufLen)
  32. {
  33. PPPTP_WORK_ITEM pWorkItem;
  34. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  35. DEBUGMSG(DBG_FUNC, (DTEXT("+ScheduleWorkItem\n")));
  36. ASSERT(ThreadingInitialized);
  37. pWorkItem = MyMemAlloc(sizeof(PPTP_WORK_ITEM), TAG_WORK_ITEM);
  38. if (pWorkItem != NULL)
  39. {
  40. pWorkItem->Context = Context;
  41. pWorkItem->pBuffer = InfoBuf;
  42. pWorkItem->Length = InfoBufLen;
  43. /*
  44. ** This interface was designed to use NdisScheduleWorkItem(), which
  45. ** would be good except that we're really only supposed to use that
  46. ** interface during startup and shutdown, due to the limited pool of
  47. ** threads available to service NdisScheduleWorkItem(). Therefore,
  48. ** instead of scheduling real work items, we simulate them, and use
  49. ** our own thread to process the calls. This also makes it easy to
  50. ** expand the size of our own thread pool, if we wish.
  51. **
  52. ** Our version is slightly different from actual NDIS_WORK_ITEMs,
  53. ** because that is an NDIS 5.0 structure, and we want people to
  54. ** (at least temporarily) build this with NDIS 4.0 headers.
  55. */
  56. pWorkItem->Callback = Callback;
  57. /*
  58. ** Our worker thread checks this list for new jobs, whenever its event
  59. ** is signalled.
  60. */
  61. MyInterlockedInsertTailList(&WorkItemList,
  62. &pWorkItem->ListEntry,
  63. &GlobalThreadLock);
  64. // Wake up our thread.
  65. KeSetEvent(&EventPassiveThread, 0, FALSE);
  66. Status = NDIS_STATUS_SUCCESS;
  67. }
  68. else
  69. {
  70. gCounters.ulWorkItemFail++;
  71. }
  72. return Status;
  73. }
  74. STATIC VOID
  75. MainPassiveLevelThread(
  76. IN OUT PVOID Context
  77. )
  78. {
  79. NDIS_STATUS Status;
  80. NTSTATUS NtStatus;
  81. PLIST_ENTRY pListEntry;
  82. PKEVENT EventList[2];
  83. DEBUGMSG(DBG_FUNC, (DTEXT("+MainPassiveLevelThread\n")));
  84. //KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
  85. EventList[0] = &EventPassiveThread;
  86. EventList[1] = &EventKillThread;
  87. for (;;)
  88. {
  89. //
  90. // The EventPassiveThread is an auto-clearing event, so
  91. // we don't need to reset the event.
  92. //
  93. NtStatus = KeWaitForMultipleObjects(2,
  94. EventList,
  95. WaitAny,
  96. Executive,
  97. KernelMode,
  98. FALSE,
  99. NULL,
  100. NULL);
  101. if (NtStatus==0) // The first event, for a work item, was signalled
  102. {
  103. while (pListEntry = MyInterlockedRemoveHeadList(&WorkItemList,
  104. &GlobalThreadLock))
  105. {
  106. PPPTP_WORK_ITEM pWorkItem = CONTAINING_RECORD(pListEntry,
  107. PPTP_WORK_ITEM,
  108. ListEntry);
  109. ASSERT(KeGetCurrentIrql()<DISPATCH_LEVEL);
  110. pWorkItem->Callback(pWorkItem);
  111. ASSERT(KeGetCurrentIrql()<DISPATCH_LEVEL);
  112. FreeWorkItem(pWorkItem);
  113. }
  114. }
  115. else
  116. {
  117. // A kill event was received.
  118. DEBUGMSG(DBG_THREAD, (DTEXT("Thread: HALT %08x\n"), NtStatus));
  119. // Free any pending requests
  120. while (pListEntry = MyInterlockedRemoveHeadList(&WorkItemList,
  121. &GlobalThreadLock))
  122. {
  123. PPPTP_WORK_ITEM pWorkItem = CONTAINING_RECORD(pListEntry,
  124. PPTP_WORK_ITEM,
  125. ListEntry);
  126. DEBUGMSG(DBG_WARN, (DTEXT("Releasing work item %08x\n"), pWorkItem));
  127. FreeWorkItem(pWorkItem);
  128. }
  129. hPassiveThread = NULL;
  130. DEBUGMSG(DBG_FUNC, (DTEXT("PsTerminateSystemThread MainPassiveLevelThread\n")));
  131. PsTerminateSystemThread(STATUS_SUCCESS);
  132. break;
  133. }
  134. }
  135. DEBUGMSG(DBG_FUNC, (DTEXT("-MainPassiveLevelThread\n")));
  136. }
  137. NDIS_STATUS
  138. CallQueueTransmitPacket(
  139. PCALL_SESSION pCall,
  140. PNDIS_WAN_PACKET pWanPacket
  141. )
  142. {
  143. NDIS_STATUS Status = NDIS_STATUS_PENDING;
  144. DEBUGMSG(DBG_FUNC, (DTEXT("+CallQueueTransmitPacket\n")));
  145. //++ProcCountTxQ[KeGetCurrentProcessorNumber()];
  146. if (!IS_CALL(pCall) || pCall->State!=STATE_CALL_ESTABLISHED)
  147. {
  148. // Drop the packet.
  149. Status = NDIS_STATUS_SUCCESS;
  150. goto cqtpDone;
  151. }
  152. NdisAcquireSpinLock(&pCall->Lock);
  153. InsertTailList(&pCall->TxPacketList, &pWanPacket->WanPacketQueue);
  154. if (!pCall->Transferring)
  155. {
  156. pCall->Transferring = TRUE;
  157. REFERENCE_OBJECT(pCall);
  158. NdisScheduleWorkItem(&pCall->SendWorkItem);
  159. }
  160. NdisReleaseSpinLock(&pCall->Lock);
  161. cqtpDone:
  162. DEBUGMSG(DBG_FUNC, (DTEXT("-CallQueueTransmitPacket\n")));
  163. return Status;
  164. }
  165. NDIS_STATUS
  166. CallQueueReceivePacket(
  167. PCALL_SESSION pCall,
  168. PDGRAM_CONTEXT pDgContext
  169. )
  170. {
  171. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  172. PGRE_HEADER pGre = pDgContext->pGreHeader;
  173. ULONG_PTR ProcNum = 0;
  174. PULONG pSequence;
  175. ULONG Sequence;
  176. DEBUGMSG(DBG_FUNC, (DTEXT("+CallQueueReceivePacket\n")));
  177. //++ProcCountRxQ[KeGetCurrentProcessorNumber()];
  178. if(!pGre->SequenceNumberPresent)
  179. {
  180. return NDIS_STATUS_FAILURE;
  181. }
  182. NdisAcquireSpinLock(&pCall->Lock);
  183. if (pCall->RxPacketsPending > 256 ||
  184. htons(pGre->KeyCallId)!=pCall->Packet.CallId ||
  185. pCall->State!=STATE_CALL_ESTABLISHED ||
  186. !IS_LINE_UP(pCall))
  187. {
  188. NdisReleaseSpinLock(&pCall->Lock);
  189. DEBUGMSG(DBG_PACKET|DBG_RX, (DTEXT("Rx: GRE CallId invalid or call in wrong state\n")));
  190. Status = NDIS_STATUS_FAILURE;
  191. goto cqrpDone;
  192. }
  193. // The packet has passed all of our tests.
  194. if (IsListEmpty(&pCall->RxPacketList))
  195. {
  196. InsertTailList(&pCall->RxPacketList, &pDgContext->ListEntry);
  197. pCall->RxPacketsPending++;
  198. }
  199. else
  200. {
  201. // There are packets already queued. Put this one in order.
  202. pSequence = (PULONG)(pGre + 1);
  203. Sequence = htonl(*pSequence);
  204. // We don't check the sequence # anymore, just put it on the queue in order
  205. {
  206. // There are packets already queued. Put this one in order.
  207. // The sequence # is the one we want soon to be the one we want.
  208. PLIST_ENTRY pListEntry;
  209. BOOLEAN OnList = FALSE;
  210. for (pListEntry = pCall->RxPacketList.Flink;
  211. pListEntry != &pCall->RxPacketList;
  212. pListEntry = pListEntry->Flink)
  213. {
  214. PDGRAM_CONTEXT pListDg = CONTAINING_RECORD(pListEntry,
  215. DGRAM_CONTEXT,
  216. ListEntry);
  217. if ((signed)htonl(GreSequence(pListDg->pGreHeader)) - (signed)Sequence > 0)
  218. {
  219. // The one on the list is newer! Put this one before it.
  220. InsertTailList(&pListDg->ListEntry, &pDgContext->ListEntry);
  221. pCall->RxPacketsPending++;
  222. OnList = TRUE;
  223. break;
  224. }
  225. }
  226. if (!OnList)
  227. {
  228. // There were no packets on this list with a greater sequence.
  229. // Put this at the end.
  230. InsertTailList(&pCall->RxPacketList, &pDgContext->ListEntry);
  231. pCall->RxPacketsPending++;
  232. }
  233. }
  234. }
  235. if (!pCall->Receiving)
  236. {
  237. pCall->Receiving = TRUE;
  238. REFERENCE_OBJECT(pCall);
  239. NdisScheduleWorkItem(&pCall->RecvWorkItem);
  240. // PptpQueueDpc(&pCall->ReceiveDpc);
  241. }
  242. NdisReleaseSpinLock(&pCall->Lock);
  243. cqrpDone:
  244. DEBUGMSG(DBG_FUNC, (DTEXT("-CallQueueReceivePacket\n")));
  245. return Status;
  246. }
  247. NDIS_STATUS
  248. InitThreading(
  249. NDIS_HANDLE hMiniportAdapter
  250. )
  251. {
  252. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  253. NTSTATUS NtStatus;
  254. UNREFERENCED_PARAMETER(hMiniportAdapter);
  255. DEBUGMSG(DBG_FUNC, (DTEXT("+InitializeThreading\n")));
  256. if (ThreadingInitialized)
  257. {
  258. ASSERT(!"Threading initialized twice");
  259. goto itDone;
  260. }
  261. NdisInitializeListHead(&WorkItemList);
  262. NdisAllocateSpinLock(&GlobalThreadLock);
  263. KeInitializeEvent(
  264. &EventPassiveThread,
  265. SynchronizationEvent, // auto-clearing event
  266. FALSE // event initially non-signalled
  267. );
  268. KeInitializeEvent(
  269. &EventKillThread,
  270. SynchronizationEvent, // auto-clearing event
  271. FALSE // event initially non-signalled
  272. );
  273. NtStatus = PsCreateSystemThread(&hPassiveThread,
  274. (ACCESS_MASK) 0L,
  275. NULL,
  276. NULL,
  277. NULL,
  278. MainPassiveLevelThread,
  279. NULL);
  280. if (NtStatus == STATUS_SUCCESS)
  281. {
  282. ThreadingInitialized = TRUE;
  283. }
  284. else
  285. {
  286. DEBUGMSG(DBG_ERROR, (DTEXT("PsCreateSystemThread failed. %08x\n"), Status));
  287. Status = NDIS_STATUS_FAILURE;
  288. goto itDone;
  289. }
  290. itDone:
  291. DEBUGMSG(DBG_FUNC, (DTEXT("-InitializeThreading %08x\n"), Status));
  292. return Status;
  293. }
  294. VOID STATIC WaitForThreadToDieAndCloseIt(HANDLE hThread, PRKEVENT pKillEvent)
  295. {
  296. PVOID pThread = NULL;
  297. NTSTATUS Status;
  298. DEBUGMSG(DBG_FUNC, (DTEXT("+WaitForThreadToDie\n")));
  299. if ( hThread != NULL && pKillEvent != NULL )
  300. {
  301. Status = ObReferenceObjectByHandle(hThread, 0, NULL, KernelMode, &pThread, NULL);
  302. if (Status==STATUS_SUCCESS)
  303. {
  304. KeSetEvent(pKillEvent, 0, FALSE);
  305. KeWaitForSingleObject(pThread, Executive, KernelMode, FALSE, NULL);
  306. ObDereferenceObject(pThread);
  307. }
  308. ZwClose(hThread);
  309. }
  310. DEBUGMSG(DBG_FUNC, (DTEXT("-WaitForThreadToDie\n")));
  311. }
  312. VOID
  313. DeinitThreading()
  314. {
  315. DEBUGMSG(DBG_FUNC, (DTEXT("+DeinitThreading\n")));
  316. ThreadingInitialized = FALSE;
  317. WaitForThreadToDieAndCloseIt( hPassiveThread,
  318. &EventKillThread );
  319. DEBUGMSG(DBG_FUNC, (DTEXT("-DeinitThreading\n")));
  320. }
  321. UCHAR TapiLineNameBuffer[64] = TAPI_LINE_NAME_STRING;
  322. ANSI_STRING TapiLineName = {
  323. sizeof(TAPI_LINE_NAME_STRING),
  324. sizeof(TapiLineNameBuffer),
  325. TapiLineNameBuffer
  326. };
  327. typedef UCHAR TAPI_CHAR_TYPE;
  328. ANSI_STRING TapiLineAddrList = { 0, 0, NULL };
  329. #define READ_NDIS_REG_ULONG(hConfig, Var, Value) \
  330. { \
  331. PNDIS_CONFIGURATION_PARAMETER RegValue; \
  332. NDIS_STATUS Status; \
  333. NDIS_STRING String = NDIS_STRING_CONST(Value); \
  334. \
  335. NdisReadConfiguration(&Status, \
  336. &RegValue, \
  337. hConfig, \
  338. &String, \
  339. NdisParameterInteger); \
  340. if (Status==NDIS_STATUS_SUCCESS) \
  341. { \
  342. (Var) = RegValue->ParameterData.IntegerData; \
  343. DEBUGMSG(DBG_INIT, (DTEXT(#Var"==%d\n"), (Var))); \
  344. } \
  345. else \
  346. { \
  347. DEBUGMSG(DBG_INIT, (DTEXT(Value", default==%d\n"), (Var)));\
  348. } \
  349. }
  350. #define READ_NDIS_REG_USHORT(hConfig, Var, Value) \
  351. { \
  352. PNDIS_CONFIGURATION_PARAMETER RegValue; \
  353. NDIS_STATUS Status; \
  354. NDIS_STRING String = NDIS_STRING_CONST(Value); \
  355. \
  356. NdisReadConfiguration(&Status, \
  357. &RegValue, \
  358. hConfig, \
  359. &String, \
  360. NdisParameterInteger); \
  361. if (Status==NDIS_STATUS_SUCCESS) \
  362. { \
  363. (Var) = (USHORT)(RegValue->ParameterData.IntegerData&0xffff); \
  364. DEBUGMSG(DBG_INIT, (DTEXT(#Var"==%d\n"), (Var))); \
  365. } \
  366. else \
  367. { \
  368. DEBUGMSG(DBG_INIT, (DTEXT(Value", default==%d\n"), (Var)));\
  369. } \
  370. }
  371. #define READ_NDIS_REG_BOOL(hConfig, Var, Value) \
  372. { \
  373. PNDIS_CONFIGURATION_PARAMETER RegValue; \
  374. NDIS_STATUS Status; \
  375. NDIS_STRING String = NDIS_STRING_CONST(Value); \
  376. \
  377. NdisReadConfiguration(&Status, \
  378. &RegValue, \
  379. hConfig, \
  380. &String, \
  381. NdisParameterInteger); \
  382. if (Status==NDIS_STATUS_SUCCESS) \
  383. { \
  384. (Var) = RegValue->ParameterData.IntegerData ? TRUE : FALSE; \
  385. DEBUGMSG(DBG_INIT, (DTEXT(#Var"==%d\n"), (Var))); \
  386. } \
  387. else \
  388. { \
  389. DEBUGMSG(DBG_INIT, (DTEXT(Value", default==%d\n"), (Var)));\
  390. } \
  391. }
  392. ULONG ReadClientAddressAndMaskList(
  393. IN NDIS_HANDLE hConfig,
  394. IN PNDIS_STRING IpAddressesString,
  395. IN PNDIS_STRING IpMasksString,
  396. IN OUT PCLIENT_ADDRESS *pClientAddressList
  397. )
  398. //
  399. // Read the IP addresses and masks in multi string formats
  400. //
  401. {
  402. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  403. PNDIS_CONFIGURATION_PARAMETER Value = NULL;
  404. ULONG ulNumIpAddresses = 0;
  405. PCLIENT_ADDRESS ClientList = NULL;
  406. *pClientAddressList = NULL;
  407. NdisReadConfiguration(&Status, // Not required value
  408. &Value,
  409. hConfig,
  410. IpAddressesString,
  411. NdisParameterMultiString);
  412. if (Status==NDIS_STATUS_SUCCESS)
  413. {
  414. ULONG i, ulAddressIndex = 0;
  415. BOOLEAN InEntry, ValidAddress;
  416. PWCHAR AddressList = Value->ParameterData.StringData.Buffer;
  417. TA_IP_ADDRESS Address;
  418. // Loop and count the addresses, so we can allocate proper size to hold them.
  419. for (i=0, InEntry=FALSE; i<(Value->ParameterData.StringData.Length/sizeof(WCHAR))-1; i++)
  420. {
  421. if (!InEntry)
  422. {
  423. if (AddressList[i]!=L'\0')
  424. {
  425. InEntry = TRUE;
  426. StringToIpAddressW(&AddressList[i],
  427. &Address,
  428. &ValidAddress);
  429. if (ValidAddress)
  430. {
  431. ulAddressIndex++;
  432. }
  433. }
  434. }
  435. else
  436. {
  437. if (AddressList[i]==L'\0')
  438. {
  439. InEntry = FALSE;
  440. }
  441. }
  442. }
  443. ulNumIpAddresses = ulAddressIndex;
  444. if (ulNumIpAddresses)
  445. {
  446. ClientList = MyMemAlloc(sizeof(CLIENT_ADDRESS)*ulNumIpAddresses, TAG_PPTP_ADDR_LIST);
  447. if (ClientList)
  448. {
  449. ulAddressIndex = 0;
  450. for (i=0, InEntry=FALSE;
  451. i<(Value->ParameterData.StringData.Length/sizeof(WCHAR))-1 && (ulAddressIndex < ulNumIpAddresses);
  452. i++)
  453. {
  454. if (!InEntry)
  455. {
  456. if (AddressList[i]!=L'\0')
  457. {
  458. InEntry = TRUE;
  459. StringToIpAddressW(&AddressList[i],
  460. &Address,
  461. &ValidAddress);
  462. if (ValidAddress)
  463. {
  464. ClientList[ulAddressIndex].Address = Address.Address[0].Address[0].in_addr;
  465. ClientList[ulAddressIndex].Mask = 0xFFFFFFFF;
  466. ulAddressIndex++;
  467. }
  468. }
  469. }
  470. else
  471. {
  472. if (AddressList[i]==L'\0')
  473. {
  474. InEntry = FALSE;
  475. }
  476. }
  477. }
  478. NdisReadConfiguration(&Status, // Not required value
  479. &Value,
  480. hConfig,
  481. IpMasksString,
  482. NdisParameterMultiString);
  483. if (Status==NDIS_STATUS_SUCCESS)
  484. {
  485. AddressList = Value->ParameterData.StringData.Buffer;
  486. ulAddressIndex = 0;
  487. for (i=0, InEntry=FALSE;
  488. i<(Value->ParameterData.StringData.Length/sizeof(WCHAR))-1 && (ulAddressIndex < ulNumIpAddresses);
  489. i++)
  490. {
  491. if (!InEntry)
  492. {
  493. if (AddressList[i]!=L'\0')
  494. {
  495. InEntry = TRUE;
  496. StringToIpAddressW(&AddressList[i],
  497. &Address,
  498. &ValidAddress);
  499. if (ValidAddress)
  500. {
  501. ClientList[ulAddressIndex].Mask = Address.Address[0].Address[0].in_addr;
  502. ulAddressIndex++;
  503. }
  504. }
  505. }
  506. else
  507. {
  508. if (AddressList[i]==L'\0')
  509. {
  510. InEntry = FALSE;
  511. }
  512. }
  513. }
  514. }
  515. for (i=0; i<ulNumIpAddresses; i++)
  516. {
  517. DEBUGMSG(DBG_INIT, (DTEXT("Client Address:%d.%d.%d.%d Mask:%d.%d.%d.%d\n"),
  518. IPADDR(ClientList[i].Address), IPADDR(ClientList[i].Mask)));
  519. }
  520. }
  521. else
  522. {
  523. ulNumIpAddresses = 0;
  524. }
  525. }
  526. }
  527. if(ulNumIpAddresses)
  528. {
  529. *pClientAddressList = ClientList;
  530. }
  531. else
  532. {
  533. ASSERT(ClientList == NULL);
  534. }
  535. return ulNumIpAddresses;
  536. }
  537. VOID
  538. OsReadConfig(
  539. NDIS_HANDLE hConfig
  540. )
  541. {
  542. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  543. PNDIS_CONFIGURATION_PARAMETER Value;
  544. NDIS_STRING TapiLineNameString = NDIS_STRING_CONST("TapiLineName");
  545. #if VER_PRODUCTVERSION_W < 0x0500
  546. NDIS_STRING TapiLineAddrString = NDIS_STRING_CONST("AddressList");
  547. #endif
  548. NDIS_STRING PeerClientIpAddressString = NDIS_STRING_CONST("ClientIpAddresses");
  549. NDIS_STRING PeerClientIpMaskString = NDIS_STRING_CONST("ClientIpMasks");
  550. NDIS_STRING TrustedIpAddressString = NDIS_STRING_CONST("TrustedIpAddresses");
  551. NDIS_STRING TrustedIpMaskString = NDIS_STRING_CONST("TrustedIpMasks");
  552. DEBUGMSG(DBG_FUNC, (DTEXT("+OsReadConfig\n")));
  553. READ_NDIS_REG_USHORT(hConfig, PptpControlPort, "TcpPortNumber");
  554. READ_NDIS_REG_ULONG (hConfig, PptpWanEndpoints, "MaxWanEndpoints");
  555. READ_NDIS_REG_ULONG (hConfig, PptpBaseCallId, "BaseCallId");
  556. READ_NDIS_REG_ULONG (hConfig, PptpMaxTransmit, "MaxTransmit");
  557. READ_NDIS_REG_ULONG (hConfig, PptpEchoTimeout, "InactivityIdleSeconds");
  558. READ_NDIS_REG_BOOL (hConfig, PptpEchoAlways, "AlwaysEcho");
  559. READ_NDIS_REG_ULONG (hConfig, CtdiTcpDisconnectTimeout, "TcpDisconnectTimeout");
  560. READ_NDIS_REG_ULONG (hConfig, CtdiTcpConnectTimeout, "TcpConnectTimeout");
  561. READ_NDIS_REG_BOOL (hConfig, PptpAuthenticateIncomingCalls, "AuthenticateIncomingCalls");
  562. READ_NDIS_REG_ULONG (hConfig, PptpTraceMask, "PptpTraceMask");
  563. READ_NDIS_REG_ULONG (hConfig, PptpValidateAddress, "ValidateAddress");
  564. READ_NDIS_REG_ULONG (hConfig, PptpMaxTunnelsPerIpAddress, "MaxTunnelsPerIpAddress");
  565. // Validate some reg values
  566. if(PptpWanEndpoints == 0)
  567. {
  568. PptpWanEndpoints = OS_DEFAULT_WAN_ENDPOINTS;
  569. }
  570. if(PptpMaxTunnelsPerIpAddress > PptpWanEndpoints)
  571. {
  572. PptpMaxTunnelsPerIpAddress = -1;
  573. }
  574. OS_RANGE_CHECK_ENDPOINTS(PptpWanEndpoints, PptpBaseCallId);
  575. OS_RANGE_CHECK_MAX_TRANSMIT(PptpMaxTransmit);
  576. // Read client IP addresses/masks to accept (old behavior)
  577. if(PptpAuthenticateIncomingCalls)
  578. {
  579. DEBUGMSG(DBG_INIT, (DTEXT("Accept IP Addresses/Masks\n")));
  580. g_ulAcceptClientAddresses = ReadClientAddressAndMaskList(
  581. hConfig,
  582. &PeerClientIpAddressString,
  583. &PeerClientIpMaskString,
  584. &g_AcceptClientList);
  585. }
  586. // Read trusted client IP addresses/masks
  587. DEBUGMSG(DBG_INIT, (DTEXT("Trsuted IP Addresses/Masks\n")));
  588. g_ulTrustedClientAddresses = ReadClientAddressAndMaskList(
  589. hConfig,
  590. &TrustedIpAddressString,
  591. &TrustedIpMaskString,
  592. &g_TrustedClientList);
  593. NdisReadConfiguration(&Status, // Not required value
  594. &Value,
  595. hConfig,
  596. &TapiLineNameString,
  597. NdisParameterString);
  598. if (Status==NDIS_STATUS_SUCCESS)
  599. {
  600. RtlUnicodeStringToAnsiString(&TapiLineName, &Value->ParameterData.StringData, FALSE);
  601. *(TAPI_CHAR_TYPE*)(TapiLineName.Buffer+TapiLineName.MaximumLength-sizeof(TAPI_CHAR_TYPE)) = (TAPI_CHAR_TYPE)0;
  602. }
  603. #if VER_PRODUCTVERSION_W < 0x0500
  604. NdisReadConfiguration(&Status, // Not required value
  605. &Value,
  606. hConfig,
  607. &TapiLineAddrString,
  608. NdisParameterMultiString);
  609. if (Status==NDIS_STATUS_SUCCESS)
  610. {
  611. RtlInitAnsiString( &TapiLineAddrList, NULL );
  612. if (RtlUnicodeStringToAnsiString(&TapiLineAddrList, &Value->ParameterData.StringData, TRUE)==NDIS_STATUS_SUCCESS)
  613. {
  614. // NT4 doesn't have the same registry value to tell us how many lines to publish.
  615. // We work around that by counting the number of address strings here
  616. PUCHAR p = TapiLineAddrList.Buffer;
  617. DEBUGMEM(DBG_TAPI, TapiLineAddrList.Buffer, TapiLineAddrList.Length, 1);
  618. PptpWanEndpoints = 0;
  619. if (p)
  620. {
  621. // Count the valid MULTI_SZ entries.
  622. while (*p++)
  623. {
  624. PptpWanEndpoints++;
  625. while (*p++); // This also skips the first NULL
  626. }
  627. }
  628. DBG_D(DBG_INIT, PptpWanEndpoints);
  629. }
  630. }
  631. #endif
  632. DEBUGMSG(DBG_FUNC, (DTEXT("-OsReadConfig\n")));
  633. }
  634. #if 0
  635. VOID OsGetFullHostName(VOID)
  636. {
  637. NTSTATUS status;
  638. OBJECT_ATTRIBUTES objattr;
  639. UNICODE_STRING uni;
  640. HANDLE hParams;
  641. KEY_VALUE_PARTIAL_INFORMATION* pNameValue;
  642. ULONG ulAllocSize, ulSize, ulIndex, ulDomainIndex;
  643. hParams = NULL;
  644. pNameValue = NULL;
  645. NdisZeroMemory(PptpHostName, MAX_HOSTNAME_LENGTH);
  646. do
  647. {
  648. // Get a handle to the TCPIP Parameters registry key.
  649. RtlInitUnicodeString(
  650. &uni,
  651. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tcpip\\Parameters" );
  652. InitializeObjectAttributes(
  653. &objattr, &uni, OBJ_CASE_INSENSITIVE, NULL, NULL );
  654. status = ZwOpenKey(&hParams, KEY_QUERY_VALUE, &objattr);
  655. if (status != STATUS_SUCCESS)
  656. {
  657. break;
  658. }
  659. ulAllocSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_HOSTNAME_LENGTH * 2;
  660. // Query the "Hostname" registry value.
  661. pNameValue = MyMemAlloc(ulAllocSize, TAG_REG);
  662. if (!pNameValue)
  663. {
  664. break;
  665. }
  666. RtlInitUnicodeString( &uni, L"Hostname");
  667. status = ZwQueryValueKey(
  668. hParams, &uni, KeyValuePartialInformation,
  669. pNameValue, ulAllocSize, &ulSize );
  670. if (status != STATUS_SUCCESS || pNameValue->Type != REG_SZ || pNameValue->DataLength < sizeof(WCHAR) * 2)
  671. {
  672. break;
  673. }
  674. // Convert host unicode to ASCII, put it in PptpHostName;
  675. ulSize = min(pNameValue->DataLength/2, MAX_HOSTNAME_LENGTH);
  676. for(ulIndex = 0; ulIndex < ulSize; ulIndex++)
  677. {
  678. PptpHostName[ulIndex] = pNameValue->Data[ulIndex*2];
  679. }
  680. // Query the "Domain" registry value.
  681. RtlInitUnicodeString( &uni, L"Domain");
  682. status = ZwQueryValueKey(
  683. hParams, &uni, KeyValuePartialInformation,
  684. pNameValue, ulAllocSize, &ulSize );
  685. // Convert domain unicode to ASCII, append it in PptpHostName;
  686. if (status == STATUS_SUCCESS
  687. && pNameValue->Type == REG_SZ
  688. && pNameValue->DataLength > sizeof(WCHAR)
  689. && ((WCHAR* )pNameValue->Data)[ 0 ] != L'\0')
  690. {
  691. PptpHostName[--ulIndex] = '.';
  692. ++ulIndex;
  693. for(ulDomainIndex = 0;
  694. ulIndex < MAX_HOSTNAME_LENGTH && ulDomainIndex < pNameValue->DataLength/2;
  695. ulIndex++, ulDomainIndex++)
  696. {
  697. PptpHostName[ulIndex] = pNameValue->Data[ulDomainIndex*2];
  698. }
  699. }
  700. PptpHostName[MAX_HOSTNAME_LENGTH -1] = '\0';
  701. }
  702. while (FALSE);
  703. if(hParams)
  704. {
  705. ZwClose(hParams);
  706. }
  707. if(pNameValue)
  708. {
  709. MyMemFree(pNameValue, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_HOSTNAME_LENGTH * 2);
  710. }
  711. }
  712. #endif
  713. VOID
  714. OsGetTapiLineAddress(ULONG Index, PUCHAR s, ULONG Length)
  715. {
  716. ASSERT(Length);
  717. #if VER_PRODUCTVERSION_W < 0x0500
  718. PUCHAR pAddr = TapiLineAddrList.Buffer;
  719. *s = 0;
  720. if (pAddr)
  721. {
  722. UINT i;
  723. for (i=0; i<Index; i++)
  724. {
  725. if (!*pAddr)
  726. {
  727. // No string at index
  728. return;
  729. }
  730. while (*pAddr) pAddr++;
  731. pAddr++;
  732. }
  733. strncpy(s, pAddr, Length);
  734. s[Length-1] = 0;
  735. }
  736. #else // VER_PRODUCTVERSION_W >= 0x0500
  737. strncpy(s, TAPI_LINE_ADDR_STRING, Length);
  738. s[Length-1] = 0;
  739. #endif
  740. }
  741. NDIS_STATUS
  742. OsSpecificTapiGetDevCaps(
  743. ULONG_PTR ulDeviceId,
  744. IN OUT PNDIS_TAPI_GET_DEV_CAPS pRequest
  745. )
  746. {
  747. PUCHAR pTmp, pTmp2;
  748. ULONG_PTR Index;
  749. DEBUGMSG(DBG_FUNC, (DTEXT("+OsSpecificTapiGetDevCaps\n")));
  750. // Convert to our internal index
  751. ulDeviceId -= pgAdapter->Tapi.DeviceIdBase;
  752. pRequest->LineDevCaps.ulStringFormat = STRINGFORMAT_ASCII;
  753. // The *6 at the end adds enough space for " 9999"
  754. pRequest->LineDevCaps.ulNeededSize = sizeof(pRequest->LineDevCaps) +
  755. sizeof(TAPI_PROVIDER_STRING) +
  756. TapiLineName.Length +
  757. sizeof(TAPI_CHAR_TYPE) * 6;
  758. if (pRequest->LineDevCaps.ulTotalSize<pRequest->LineDevCaps.ulNeededSize)
  759. {
  760. DEBUGMSG(DBG_FUNC|DBG_WARN, (DTEXT("-TapiGetDevCaps NDIS_STATUS_SUCCESS without PROVIDER or LINE_NAME strings\n")));
  761. return NDIS_STATUS_SUCCESS;
  762. }
  763. // Tack the provider string to the end of the LineDevCaps structure.
  764. pRequest->LineDevCaps.ulProviderInfoSize = sizeof(TAPI_PROVIDER_STRING);
  765. pRequest->LineDevCaps.ulProviderInfoOffset = sizeof(pRequest->LineDevCaps);
  766. pTmp = ((PUCHAR)&pRequest->LineDevCaps) + sizeof(pRequest->LineDevCaps);
  767. NdisMoveMemory(pTmp, TAPI_PROVIDER_STRING, sizeof(TAPI_PROVIDER_STRING));
  768. pTmp += sizeof(TAPI_PROVIDER_STRING);
  769. // Tack on the LineName after the provider string.
  770. pRequest->LineDevCaps.ulLineNameSize = TapiLineName.Length + sizeof(TAPI_CHAR_TYPE);
  771. pRequest->LineDevCaps.ulLineNameOffset = pRequest->LineDevCaps.ulProviderInfoOffset +
  772. pRequest->LineDevCaps.ulProviderInfoSize;
  773. NdisMoveMemory(pTmp, TapiLineName.Buffer, TapiLineName.Length+sizeof(TAPI_CHAR_TYPE));
  774. while (*pTmp) pTmp++; // Find the NULL
  775. *pTmp++ = ' ';
  776. pRequest->LineDevCaps.ulLineNameSize++;
  777. // Put a number at the end of the string.
  778. if (ulDeviceId==0)
  779. {
  780. *pTmp++ = '0';
  781. *pTmp++ = '\0';
  782. pRequest->LineDevCaps.ulLineNameSize += 2;
  783. }
  784. else
  785. {
  786. Index = ulDeviceId;
  787. ASSERT(Index<100000);
  788. if(Index >= 100000)
  789. {
  790. // Index value is usually small, but just make sure it's within boundary
  791. Index = 99999;
  792. }
  793. pTmp2 = pTmp;
  794. while (Index)
  795. {
  796. *pTmp2++ = (UCHAR)((Index%10) + '0');
  797. Index /= 10;
  798. pRequest->LineDevCaps.ulLineNameSize++;
  799. }
  800. *pTmp2-- = '\0'; // Null terminate and point to the last digit.
  801. pRequest->LineDevCaps.ulLineNameSize++;
  802. // We put the number in backwards, now reverse it.
  803. while (pTmp<pTmp2)
  804. {
  805. UCHAR t = *pTmp;
  806. *pTmp++ = *pTmp2;
  807. *pTmp2-- = t;
  808. }
  809. }
  810. pRequest->LineDevCaps.ulUsedSize = pRequest->LineDevCaps.ulNeededSize;
  811. DEBUGMSG(DBG_FUNC, (DTEXT("-OsSpecificTapiGetDevCaps\n")));
  812. return NDIS_STATUS_SUCCESS;
  813. }