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.

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