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.

1183 lines
23 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. svccom.cxx
  5. Abstract:
  6. Contains code that is common to both client and server side of
  7. the service location protocol..
  8. Author:
  9. Madan Appiah (madana) 15-May-1995
  10. Environment:
  11. User Mode - Win32
  12. Revision History:
  13. --*/
  14. #include <svcloc.hxx>
  15. DWORD g_cInitializers = 0;
  16. //
  17. // include global.h one more time to alloc global data.
  18. //
  19. //
  20. // to enable second time include.
  21. //
  22. #undef _GLOBAL_
  23. #undef EXTERN
  24. //
  25. // to allocate data
  26. //
  27. #define GLOBAL_SVC_DATA_ALLOCATE
  28. #include <global.h>
  29. DWORD
  30. MakeSapServiceName(
  31. LPSTR SapNameBuffer,
  32. DWORD SapNameBufferLen
  33. )
  34. /*++
  35. Routine Description:
  36. This routine generates a sap service name. The first part of the name
  37. is computername and last part is the string version of service guid.
  38. Arguments:
  39. SapNameBuffer - pointer to a sap name buffer where sap name is
  40. returned.
  41. SapNameBufferLen - length of the above buffer.
  42. Return Value:
  43. pointer to sap service name..
  44. --*/
  45. {
  46. TcpsvcsDbgAssert( SapNameBufferLen >= (SAP_SERVICE_NAME_LEN + 1));
  47. if( SapNameBufferLen < SAP_SERVICE_NAME_LEN + 1) {
  48. return( ERROR_INSUFFICIENT_BUFFER );
  49. }
  50. //
  51. // Get Computername.
  52. //
  53. DWORD Len = SapNameBufferLen;
  54. if( !GetComputerNameA( SapNameBuffer, &Len ) ) {
  55. DWORD Error = GetLastError();
  56. TcpsvcsDbgPrint(( DEBUG_ERRORS,
  57. "GetComputerNameA failed, %ld.\n", Error ));
  58. return( Error );
  59. }
  60. TcpsvcsDbgAssert( Len <= MAX_COMPUTERNAME_LENGTH );
  61. while( Len < MAX_COMPUTERNAME_LENGTH ) {
  62. SapNameBuffer[Len++] = '!';
  63. }
  64. //
  65. // append GUID.
  66. //
  67. strcpy( SapNameBuffer + Len, SERVICE_GUID_STR );
  68. return( ERROR_SUCCESS );
  69. }
  70. VOID
  71. MakeUniqueServerName(
  72. LPBYTE StrBuffer,
  73. DWORD StrBufferLen,
  74. LPSTR ComputerName
  75. )
  76. /*++
  77. Routine Description:
  78. This routine makes an unique name used by the server to listen to
  79. the client discovery requests.
  80. Arguments:
  81. StrBuffer : pointer to a buffer where the unique name is returned.
  82. StrBufferLen : length of the above buffer.
  83. ComputerName : pointer to the computer that is used to form the unique
  84. name.
  85. Return Value:
  86. none.
  87. --*/
  88. {
  89. DWORD ComputerNameLen = strlen(ComputerName);
  90. DWORD BufLen = StrBufferLen;
  91. LPBYTE Buffer = StrBuffer;
  92. memset( Buffer, 0x0, BufLen );
  93. memcpy(
  94. Buffer,
  95. NETBIOS_INET_SERVER_UNIQUE_NAME,
  96. NETBIOS_INET_SERVER_UNIQUE_NAME_LEN );
  97. BufLen -= NETBIOS_INET_SERVER_UNIQUE_NAME_LEN;
  98. Buffer += NETBIOS_INET_SERVER_UNIQUE_NAME_LEN;
  99. if( BufLen >= ComputerNameLen ) {
  100. //
  101. // we enough space in the buffer to append computername.
  102. //
  103. memcpy( Buffer,ComputerName, ComputerNameLen );
  104. return;
  105. }
  106. //
  107. // buffer does not have enough space, chop off few chars from the
  108. // begining of the computername.
  109. //
  110. memcpy( Buffer, ComputerName + (ComputerNameLen - BufLen), BufLen );
  111. return;
  112. }
  113. #if 0
  114. VOID
  115. AppendRandomChar(
  116. LPSTR String
  117. )
  118. /*++
  119. Routine Description:
  120. This routine adds a random char to the end of the given string. It is
  121. assumed that the given string has a space for the new char.
  122. Arguments:
  123. String : pointer to a string where a random char is added.
  124. Return Value:
  125. none.
  126. --*/
  127. {
  128. CHAR RandChar;
  129. DWORD RandNum;
  130. RandNum = (DWORD)rand();
  131. RandNum = RandNum % (26 + 10); // 26 alphabets, and 10 numerics
  132. if( RandNum < 10 ) {
  133. RandChar = (CHAR)('0'+ RandNum);
  134. }
  135. else {
  136. RandChar = (CHAR)('A'+ RandNum - 10);
  137. }
  138. DWORD Len = strlen(String);
  139. //
  140. // append random char.
  141. //
  142. String[Len] = RandChar;
  143. String[Len + 1] = '\0';
  144. return;
  145. }
  146. #endif //0
  147. DWORD
  148. ComputeCheckSum(
  149. LPBYTE Buffer,
  150. DWORD BufferLength
  151. )
  152. /*++
  153. Routine Description:
  154. This function computes the check sum of the given buffer by ex-or'ing
  155. the dwords. It is assumed that the buffer DWORD aligned and the buffer
  156. length is multiples of DWORD.
  157. Arguments:
  158. Buffer : pointer to a buffer whose check sum to be computed.
  159. BufferLength : length of the above buffer.
  160. Return Value:
  161. Check sum.
  162. --*/
  163. {
  164. DWORD CheckSum = 0;
  165. LPDWORD BufferPtr = (LPDWORD)Buffer;
  166. LPBYTE EndBuffer = Buffer + BufferLength;
  167. TcpsvcsDbgAssert( (ULONG_PTR)Buffer % sizeof(DWORD) == 0 );
  168. // alignment check.
  169. TcpsvcsDbgAssert( BufferLength % sizeof(DWORD) == 0 );
  170. // multiple DWORD check.
  171. while( (LPBYTE)BufferPtr < EndBuffer ) {
  172. CheckSum ^= *BufferPtr;
  173. BufferPtr++;
  174. }
  175. return( CheckSum );
  176. }
  177. BOOL
  178. DLLSvclocEntry(
  179. IN HINSTANCE DllHandle,
  180. IN DWORD Reason,
  181. IN LPVOID Reserved
  182. )
  183. /*++
  184. Routine Description:
  185. Performs global initialization and termination for all protocol modules.
  186. This function only handles process attach and detach which are required for
  187. global initialization and termination, respectively. We disable thread
  188. attach and detach. New threads calling Wininet APIs will get an
  189. INTERNET_THREAD_INFO structure created for them by the first API requiring
  190. this structure
  191. Arguments:
  192. DllHandle - handle of this DLL. Unused
  193. Reason - process attach/detach or thread attach/detach
  194. Reserved - if DLL_PROCESS_ATTACH, NULL means DLL is being dynamically
  195. loaded, else static. For DLL_PROCESS_DETACH, NULL means DLL
  196. is being freed as a consequence of call to FreeLibrary()
  197. else the DLL is being freed as part of process termination
  198. Return Value:
  199. BOOL
  200. Success - TRUE
  201. Failure - FALSE. Failed to initialize
  202. --*/
  203. {
  204. BOOL ok;
  205. DWORD error;
  206. UNREFERENCED_PARAMETER(DllHandle);
  207. //
  208. // perform global dll initialization, if any.
  209. //
  210. switch (Reason) {
  211. case DLL_PROCESS_ATTACH:
  212. //
  213. // we switch off thread library calls to avoid taking a hit for every
  214. // thread creation/termination that happens in this process, regardless
  215. // of whether Internet APIs are called in the thread.
  216. //
  217. // If a new thread does make Internet API calls that require a per-thread
  218. // structure then the individual API will create one
  219. //
  220. DisableThreadLibraryCalls(DllHandle);
  221. //
  222. // Old Normandy servers that are in our process are assuming the
  223. // service locator is initialized by DLL_PROCESS_ATTACH and terminated
  224. // by PROCESS_DETACH. Since the service locator has a thread we
  225. // can't safely cleanup during process_detach so we do an extra
  226. // loadlibrary on ourselves and remain in process. When the Normandy
  227. // servers are updated, remove this.
  228. //
  229. if ( !InitSvcLocator() ||
  230. !LoadLibrary( "inetsloc.dll" ))
  231. {
  232. return FALSE;
  233. }
  234. break;
  235. case DLL_PROCESS_DETACH:
  236. break;
  237. }
  238. return (TRUE);
  239. }
  240. BOOL
  241. InitSvcLocator(
  242. VOID
  243. )
  244. {
  245. //
  246. // We assume the caller is serializing access from multiple initializers.
  247. // The callers will presumably be just infocomm.dll that does do the
  248. // serialization.
  249. //
  250. //
  251. if ( g_cInitializers++ ) {
  252. return TRUE;
  253. }
  254. if ( DllProcessAttachSvcloc() != ERROR_SUCCESS ) {
  255. return FALSE;
  256. }
  257. return TRUE;
  258. }
  259. BOOL
  260. TerminateSvcLocator(
  261. VOID
  262. )
  263. {
  264. if ( --g_cInitializers )
  265. return TRUE;
  266. DllProcessDetachSvcloc();
  267. return TRUE;
  268. }
  269. DWORD
  270. DllProcessAttachSvcloc(
  271. VOID
  272. )
  273. /*++
  274. Routine Description:
  275. This dll init function initializes service location global variables.
  276. Arguments:
  277. NONE.
  278. Return Value:
  279. Windows Error Code.
  280. --*/
  281. {
  282. DWORD Error;
  283. //
  284. // initialize global variables.
  285. //
  286. // DebugBreak();
  287. #if DBG
  288. //
  289. // initialize dbg crit sect.
  290. //
  291. INITIALIZE_CRITICAL_SECTION( &GlobalDebugCritSect );
  292. GlobalDebugFlag = DEBUG_ERRORS;
  293. #endif // DBG
  294. INITIALIZE_CRITICAL_SECTION( &GlobalSvclocCritSect );
  295. LOCK_SVC_GLOBAL_DATA();
  296. GlobalComputerName[0] = '\0';
  297. GlobalSrvRegistered = FALSE;
  298. SvclocHeap = new MEMORY;
  299. if( SvclocHeap == NULL ) {
  300. UNLOCK_SVC_GLOBAL_DATA();
  301. return( ERROR_NOT_ENOUGH_MEMORY );
  302. }
  303. GlobalSrvInfoObj = NULL;
  304. GlobalSrvRespMsg = NULL;
  305. GlobalSrvRespMsgLength = 0;
  306. GlobalSrvAllotedRespMsgLen = 0;
  307. GlobalWinsockStarted = FALSE;
  308. GlobalRNRRegistered = FALSE;
  309. GlobalSrvListenThreadHandle = NULL;
  310. memset( &GlobalSrvSockets, 0x0, sizeof(GlobalSrvSockets) );
  311. GlobalCliDiscoverThreadHandle = NULL;
  312. GlobalCliQueryMsg = NULL;
  313. GlobalCliQueryMsgLen = 0;
  314. GlobalSapGuid.Data1 = ssgData1;
  315. GlobalSapGuid.Data2 = ssgData2;
  316. GlobalSapGuid.Data3 = ssgData3;
  317. GlobalSapGuid.Data4[0] = ssgData41;
  318. GlobalSapGuid.Data4[1] = ssgData42;
  319. GlobalSapGuid.Data4[2] = ssgData43;
  320. GlobalSapGuid.Data4[3] = ssgData44;
  321. GlobalSapGuid.Data4[4] = ssgData45;
  322. GlobalSapGuid.Data4[5] = ssgData46;
  323. GlobalSapGuid.Data4[6] = ssgData47;
  324. GlobalSapGuid.Data4[7] = ssgData48;
  325. InitializeListHead( &GlobalCliQueryRespList );
  326. memset( &GlobalCliSockets, 0x0, sizeof(GlobalCliSockets) );
  327. memset( &GlobalCliNBSockets, 0x0, sizeof(GlobalCliNBSockets) );
  328. GlobalCliIpxSocket = INVALID_SOCKET;
  329. GlobalDiscoveryInProgressEvent =
  330. IIS_CREATE_EVENT(
  331. "GlobalDiscoveryInProgressEvent",
  332. &GlobalDiscoveryInProgressEvent,
  333. TRUE, // MANUAL reset
  334. TRUE // initial state: signalled
  335. );
  336. if ( GlobalDiscoveryInProgressEvent == NULL ) {
  337. Error = GetLastError();
  338. UNLOCK_SVC_GLOBAL_DATA();
  339. return(Error);
  340. }
  341. GlobalLastDiscoveryTime = 0;
  342. //
  343. // get platform type.
  344. //
  345. OSVERSIONINFO VersionInfo;
  346. VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
  347. if ( (GetVersionEx(&VersionInfo)) ) {
  348. GlobalPlatformType = VersionInfo.dwPlatformId;
  349. }
  350. else {
  351. UNLOCK_SVC_GLOBAL_DATA();
  352. return( ERROR_INSUFFICIENT_BUFFER );
  353. }
  354. GlobalNumNBPendingRecvs = 0;
  355. GlobalNBPendingRecvs = NULL;
  356. InitializeListHead( &GlobalWin31NBRespList );
  357. GlobalWin31NumNBResps = 0;
  358. UNLOCK_SVC_GLOBAL_DATA();
  359. srand( (unsigned)time(NULL));
  360. return( ERROR_SUCCESS );
  361. }
  362. DWORD
  363. DllProcessDetachSvcloc(
  364. VOID
  365. )
  366. /*++
  367. Routine Description:
  368. This fundtion frees the global service location objects.
  369. Arguments:
  370. NONE.
  371. Return Value:
  372. Windows Error Code.
  373. --*/
  374. {
  375. LOCK_SVC_GLOBAL_DATA();
  376. if( GlobalSrvRegistered ) {
  377. ServerDeregisterAndStopListen();
  378. }
  379. if( GlobalSrvInfoObj != NULL ) {
  380. delete GlobalSrvInfoObj;
  381. GlobalSrvInfoObj = NULL;
  382. }
  383. if( GlobalSrvRespMsg != NULL ) {
  384. SvclocHeap->Free( GlobalSrvRespMsg );
  385. GlobalSrvRespMsg = NULL;
  386. GlobalSrvRespMsgLength = 0;
  387. GlobalSrvAllotedRespMsgLen = 0;
  388. }
  389. if( GlobalSrvRecvBuf != NULL ) {
  390. SvclocHeap->Free( GlobalSrvRecvBuf );
  391. GlobalSrvRecvBuf = NULL;
  392. GlobalSrvRecvBufLength = 0;
  393. }
  394. if( GlobalCliQueryMsg != NULL ) {
  395. SvclocHeap->Free( GlobalCliQueryMsg );
  396. GlobalCliQueryMsg = NULL;
  397. GlobalCliQueryMsgLen = 0;
  398. }
  399. InitializeListHead( &GlobalCliQueryRespList );
  400. while( !IsListEmpty( &GlobalCliQueryRespList ) ) {
  401. LPCLIENT_QUERY_RESPONSE QueryResponse;
  402. //
  403. // remove head entry and free it up.
  404. //
  405. QueryResponse = (LPCLIENT_QUERY_RESPONSE)
  406. RemoveHeadList( &GlobalCliQueryRespList );
  407. //
  408. // free response buffer.
  409. //
  410. SvclocHeap->Free( QueryResponse->ResponseBuffer );
  411. //
  412. // free this node.
  413. //
  414. SvclocHeap->Free( QueryResponse );
  415. }
  416. //
  417. // close client sockets.
  418. //
  419. DWORD i;
  420. for( i = 0; i < GlobalCliSockets.fd_count; i++ ) {
  421. closesocket( GlobalCliSockets.fd_array[i] );
  422. }
  423. //
  424. // invalidate client handles.
  425. //
  426. memset( &GlobalCliSockets, 0x0, sizeof(GlobalCliSockets) );
  427. memset( &GlobalCliNBSockets, 0x0, sizeof(GlobalCliNBSockets) );
  428. GlobalCliIpxSocket = INVALID_SOCKET;
  429. //
  430. // stop client discovery thread.
  431. //
  432. if( GlobalCliDiscoverThreadHandle != NULL ) {
  433. //
  434. // Wait for the client discovery thread to stop, but don't wait
  435. // for longer than THREAD_TERMINATION_TIMEOUT msecs (60 secs)
  436. //
  437. DWORD WaitStatus =
  438. WaitForSingleObject(
  439. GlobalCliDiscoverThreadHandle,
  440. THREAD_TERMINATION_TIMEOUT );
  441. TcpsvcsDbgAssert( WaitStatus != WAIT_FAILED );
  442. if( WaitStatus == WAIT_FAILED ) {
  443. TcpsvcsDbgPrint((DEBUG_ERRORS,
  444. "WaitForSingleObject call failed, %ld\n", GetLastError() ));
  445. }
  446. CloseHandle( GlobalCliDiscoverThreadHandle );
  447. GlobalCliDiscoverThreadHandle = NULL;
  448. }
  449. if( GlobalWinsockStarted ) {
  450. WSACleanup();
  451. GlobalWinsockStarted = FALSE;
  452. }
  453. TcpsvcsDbgAssert( GlobalNumNBPendingRecvs == 0)
  454. TcpsvcsDbgAssert( GlobalNBPendingRecvs == NULL );
  455. if( GlobalNBPendingRecvs != NULL ) {
  456. SvclocHeap->Free( GlobalNBPendingRecvs );
  457. }
  458. TcpsvcsDbgAssert( GlobalWin31NumNBResps == 0)
  459. TcpsvcsDbgAssert( IsListEmpty( &GlobalWin31NBRespList ) == TRUE );
  460. //
  461. // free response list.
  462. //
  463. while ( !IsListEmpty( &GlobalWin31NBRespList ) ) {
  464. PLIST_ENTRY Entry;
  465. Entry = RemoveHeadList( &GlobalWin31NBRespList );
  466. //
  467. // free response buffer if it is not used.
  468. //
  469. if( ((LPSVCLOC_NETBIOS_RESP_ENTRY)
  470. Entry)->Resp.ResponseBuffer != NULL ) {
  471. SvclocHeap->Free(
  472. ((LPSVCLOC_NETBIOS_RESP_ENTRY)
  473. Entry)->Resp.ResponseBuffer );
  474. }
  475. SvclocHeap->Free( Entry );
  476. }
  477. if( SvclocHeap != NULL ) {
  478. delete SvclocHeap;
  479. SvclocHeap = NULL;
  480. }
  481. if( GlobalDiscoveryInProgressEvent != NULL ) {
  482. CloseHandle( GlobalDiscoveryInProgressEvent );
  483. GlobalDiscoveryInProgressEvent = NULL;
  484. }
  485. GlobalLastDiscoveryTime = 0;
  486. UNLOCK_SVC_GLOBAL_DATA();
  487. DeleteCriticalSection( &GlobalSvclocCritSect );
  488. #if DBG
  489. //
  490. // Delete dbg crit sect.
  491. //
  492. DeleteCriticalSection( &GlobalDebugCritSect );
  493. #endif // DBG
  494. return( ERROR_SUCCESS );
  495. }
  496. VOID
  497. FreeServiceInfo(
  498. LPINET_SERVICE_INFO ServiceInfo
  499. )
  500. /*++
  501. Routine Description:
  502. This function frees the memory blocks consumed by the service info
  503. structure.
  504. Arguments:
  505. ServiceInfo : pointer to a service info structure.
  506. Return Value:
  507. None.
  508. --*/
  509. {
  510. TcpsvcsDbgAssert( ServiceInfo != NULL );
  511. if( ServiceInfo == NULL ) {
  512. return;
  513. }
  514. //
  515. // free all leaves of the tree first and then branches.
  516. //
  517. //
  518. // free service comment.
  519. //
  520. if( ServiceInfo->ServiceComment != NULL ) {
  521. SvclocHeap->Free( ServiceInfo->ServiceComment );
  522. }
  523. if( ServiceInfo->Bindings.NumBindings ) {
  524. TcpsvcsDbgAssert( ServiceInfo->Bindings.BindingsInfo != NULL );
  525. if( ServiceInfo->Bindings.BindingsInfo != NULL ) {
  526. DWORD i;
  527. for( i = 0; i < ServiceInfo->Bindings.NumBindings; i++ ) {
  528. if( ServiceInfo->Bindings.BindingsInfo[i].BindData != NULL ) {
  529. SvclocHeap->Free( ServiceInfo->Bindings.BindingsInfo[i].BindData );
  530. }
  531. }
  532. SvclocHeap->Free( ServiceInfo->Bindings.BindingsInfo );
  533. }
  534. }
  535. else {
  536. TcpsvcsDbgAssert( ServiceInfo->Bindings.BindingsInfo == NULL );
  537. }
  538. SvclocHeap->Free( ServiceInfo );
  539. return;
  540. }
  541. VOID
  542. FreeServerInfo(
  543. LPINET_SERVER_INFO ServerInfo
  544. )
  545. /*++
  546. Routine Description:
  547. This function frees the memory blocks consumed by the server info
  548. structure.
  549. Arguments:
  550. ServerInfo : pointer to a server info structure.
  551. Return Value:
  552. None.
  553. --*/
  554. {
  555. DWORD i;
  556. if( ServerInfo != NULL ) {
  557. //
  558. // first free all service info.
  559. //
  560. if( ServerInfo->Services.NumServices > 0 ) {
  561. TcpsvcsDbgAssert( ServerInfo->Services.Services != NULL );
  562. }
  563. for ( i = 0; i < ServerInfo->Services.NumServices; i++) {
  564. FreeServiceInfo( ServerInfo->Services.Services[i] );
  565. }
  566. //
  567. // now free services pointer array.
  568. //
  569. if( ServerInfo->Services.Services != NULL ) {
  570. SvclocHeap->Free( ServerInfo->Services.Services );
  571. }
  572. //
  573. // free server address.
  574. //
  575. if( ServerInfo->ServerAddress.BindData != NULL ) {
  576. SvclocHeap->Free( ServerInfo->ServerAddress.BindData );
  577. }
  578. //
  579. // free server name.
  580. //
  581. if( ServerInfo->ServerName != NULL ) {
  582. SvclocHeap->Free( ServerInfo->ServerName );
  583. }
  584. //
  585. // now server info structure.
  586. //
  587. SvclocHeap->Free( ServerInfo );
  588. }
  589. return;
  590. }
  591. VOID
  592. FreeServersList(
  593. LPINET_SERVERS_LIST ServersList
  594. )
  595. /*++
  596. Routine Description:
  597. This function frees the memory blocks consumed by the servers list
  598. structure.
  599. Arguments:
  600. ServersList : pointer to a servers liststructure.
  601. Return Value:
  602. None.
  603. --*/
  604. {
  605. if( ServersList != NULL ) {
  606. //
  607. // free server info structures.
  608. //
  609. if( ServersList->NumServers > 0 ) {
  610. TcpsvcsDbgAssert( ServersList->Servers != NULL );
  611. }
  612. DWORD i;
  613. for( i = 0; i < ServersList->NumServers; i++ ) {
  614. FreeServerInfo( ServersList->Servers[i] );
  615. }
  616. //
  617. // free servers info pointer array.
  618. //
  619. if( ServersList->Servers != NULL ) {
  620. SvclocHeap->Free( ServersList->Servers );
  621. }
  622. //
  623. // servers list structure.
  624. //
  625. SvclocHeap->Free( ServersList );
  626. }
  627. return;
  628. }
  629. BOOL
  630. GetNetBiosLana(
  631. PLANA_ENUM pLanas
  632. )
  633. /*++
  634. Routine Description:
  635. This function enumurate all netbios lana on the system.
  636. Arguments:
  637. pLanas - pointer to LANA_ENUM structure where enum is returned.
  638. Return Value:
  639. TRUE - if successed.
  640. FALSE - otherwise.
  641. --*/
  642. {
  643. NCB NetBiosNCB;
  644. UCHAR NBErrorCode;
  645. memset( &NetBiosNCB, 0, sizeof(NetBiosNCB) );
  646. NetBiosNCB.ncb_command = NCBENUM;
  647. NetBiosNCB.ncb_buffer = (PUCHAR)pLanas;
  648. NetBiosNCB.ncb_length = sizeof(LANA_ENUM);
  649. NBErrorCode = Netbios( &NetBiosNCB );
  650. if( (NBErrorCode == NRC_GOODRET) &&
  651. (NetBiosNCB.ncb_retcode == NRC_GOODRET) ) {
  652. return( TRUE );
  653. }
  654. TcpsvcsDbgPrint(( DEBUG_ERRORS, "NetBios() failed, %ld, %ld \n",
  655. NBErrorCode, NetBiosNCB.ncb_retcode ));
  656. return( FALSE );
  657. }
  658. BOOL
  659. GetEnumNBLana(
  660. PLANA_ENUM pLanas
  661. )
  662. /*++
  663. Routine Description:
  664. This function enumurate all netbios lana on the system.
  665. Arguments:
  666. pLanas - pointer to LANA_ENUM structure where enum is returned.
  667. Return Value:
  668. TRUE - if successed.
  669. FALSE - otherwise.
  670. --*/
  671. {
  672. DWORD Error;
  673. INT ProtocolCount;
  674. PPROTOCOL_INFO ProtocolBuffer = NULL;
  675. DWORD ProtocolBufferSize = 0;
  676. //
  677. // init return value.
  678. //
  679. pLanas->length = 0;
  680. //
  681. // determine the enum buffer size required.
  682. //
  683. ProtocolCount = EnumProtocols(
  684. NULL,
  685. NULL,
  686. &ProtocolBufferSize );
  687. if( ProtocolCount == SOCKET_ERROR ) {
  688. Error = WSAGetLastError();
  689. if( Error != ERROR_INSUFFICIENT_BUFFER ) {
  690. goto Cleanup;
  691. }
  692. }
  693. if( (ProtocolBufferSize == 0) || (ProtocolCount == 0) ) {
  694. Error = ERROR_SUCCESS;
  695. goto Cleanup;
  696. }
  697. //
  698. // allocate memory for the protocol buffer.
  699. //
  700. ProtocolBuffer =
  701. (PPROTOCOL_INFO)SvclocHeap->Alloc( ProtocolBufferSize );
  702. if( ProtocolBuffer == NULL ) {
  703. Error = ERROR_NOT_ENOUGH_MEMORY;
  704. goto Cleanup;
  705. }
  706. //
  707. // now enum protocols.
  708. //
  709. ProtocolCount = EnumProtocols(
  710. NULL,
  711. ProtocolBuffer,
  712. &ProtocolBufferSize );
  713. if( ProtocolCount == SOCKET_ERROR ) {
  714. Error = WSAGetLastError();
  715. goto Cleanup;
  716. }
  717. TcpsvcsDbgAssert( ProtocolCount > 0 );
  718. //
  719. // now filter net bios protcols only and get the corresponding lana
  720. // values.
  721. //
  722. DWORD i;
  723. for ( i = 0; i < (DWORD)ProtocolCount; i++ ) {
  724. if( ProtocolBuffer[i].iAddressFamily == AF_NETBIOS ) {
  725. if( pLanas->length < MAX_LANA ) {
  726. UCHAR Lana;
  727. DWORD j;
  728. Lana = (UCHAR)((INT)ProtocolBuffer[i].iProtocol * (-1));
  729. //
  730. // if this is a new lana add to list.
  731. //
  732. for ( j = 0; j < pLanas->length ; j++ ) {
  733. if( pLanas->lana[j] == Lana ) {
  734. break;
  735. }
  736. }
  737. if( j >= pLanas->length ) {
  738. pLanas->lana[pLanas->length] = Lana;
  739. pLanas->length++;
  740. }
  741. }
  742. }
  743. }
  744. Error = ERROR_SUCCESS;
  745. Cleanup:
  746. if( ProtocolBuffer != NULL ) {
  747. SvclocHeap->Free( ProtocolBuffer );
  748. }
  749. if( Error != ERROR_SUCCESS ) {
  750. TcpsvcsDbgPrint(( DEBUG_ERRORS,
  751. "GetNetBiosLana failed, %ld\n", Error ));
  752. return( FALSE );
  753. }
  754. return( TRUE );
  755. }
  756. BOOL
  757. MakeNBSocketForLana(
  758. UCHAR Lana,
  759. PSOCKADDR pSocketAddress,
  760. SOCKET *pNBSocket
  761. )
  762. /*++
  763. Routine Description:
  764. This function possibly creates a socket for the given lana and binds
  765. to the given socket address.
  766. ASSUME : global data crit sect is locked.
  767. Arguments:
  768. Lana : lana number for the new sockets.
  769. pSocketAddress : pointer to a socket address to bind to.
  770. pNBSocket : pointer to a location where the new socket is returned.
  771. Return Value:
  772. TRUE : if successfully created a socket and bound to the given nb
  773. addresse.
  774. FALSE : otherwise.
  775. --*/
  776. {
  777. DWORD Error;
  778. SOCKET NBSocket;
  779. DWORD Arg = 1;
  780. *pNBSocket = INVALID_SOCKET;
  781. //
  782. // create a socket for this lana.
  783. //
  784. NBSocket = socket( AF_NETBIOS, SOCK_DGRAM, Lana );
  785. if( NBSocket == INVALID_SOCKET ) {
  786. Error = WSAGetLastError();
  787. TcpsvcsDbgPrint(( DEBUG_ERRORS, "socket() failed, %ld\n", Error ));
  788. //
  789. // something wrong with this lana, try rest.
  790. //
  791. return( FALSE );
  792. }
  793. //
  794. // make this socket non blocking.
  795. //
  796. if( (ioctlsocket( NBSocket, FIONBIO, &Arg )) == SOCKET_ERROR ) {
  797. Error = WSAGetLastError();
  798. TcpsvcsDbgPrint(( DEBUG_ERRORS, "ioctlsocket() failed, %ld\n", Error ));
  799. //
  800. // something wrong with this lana, try rest.
  801. //
  802. closesocket( NBSocket );
  803. return( FALSE );
  804. }
  805. //
  806. // bind to this socket.
  807. //
  808. if( bind(
  809. NBSocket,
  810. pSocketAddress,
  811. sizeof(SOCKADDR_NB) ) == SOCKET_ERROR ) {
  812. Error = WSAGetLastError();
  813. TcpsvcsDbgPrint(( DEBUG_ERRORS, "ioctlsocket() failed, %ld\n", Error ));
  814. //
  815. // something wrong with this lana, try rest.
  816. //
  817. closesocket( NBSocket );
  818. return( FALSE );
  819. }
  820. *pNBSocket = NBSocket;
  821. return( TRUE );
  822. }