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.

1500 lines
30 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. svcinfo.cxx
  5. Abstract:
  6. contains class implementation of service location classes.
  7. Author:
  8. Madan Appiah (madana) 15-May-1995
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. Sean Woodward (t-seanwo) 26-October-1997 ADSI Update
  13. --*/
  14. #include <svcloc.hxx>
  15. DWORD
  16. EMBED_SERVICE_INFO::ComputeServiceInfoSize(
  17. LPINET_SERVICE_INFO ServiceInfo
  18. )
  19. /*++
  20. Routine Description:
  21. This private member function computes the size of the embedded service
  22. info buffer.
  23. Arguments:
  24. ServiceInfo : pointer to a service info structure.
  25. Return Value:
  26. size of the embedded service info buffer.
  27. --*/
  28. {
  29. DWORD Size;
  30. DWORD NumBindings;
  31. LPINET_BIND_INFO BindingsInfo;
  32. DWORD i;
  33. DWORD ServiceCommentLen;
  34. if( ServiceInfo->ServiceComment != NULL) {
  35. ServiceCommentLen =
  36. ROUND_UP_COUNT(
  37. (strlen(ServiceInfo->ServiceComment) + 1) * sizeof(CHAR),
  38. ALIGN_DWORD);
  39. }
  40. else {
  41. ServiceCommentLen = ROUND_UP_COUNT( 1, ALIGN_DWORD );
  42. }
  43. Size =
  44. sizeof(ULONGLONG) + // service mask
  45. sizeof(INET_SERVICE_STATE) + // service state
  46. ServiceCommentLen + // service comment
  47. sizeof(DWORD); // NumBindings
  48. NumBindings = ServiceInfo->Bindings.NumBindings;
  49. BindingsInfo = ServiceInfo->Bindings.BindingsInfo;
  50. if( NumBindings != 0 ) {
  51. TcpsvcsDbgAssert( BindingsInfo != NULL )
  52. for( i = 0; i < NumBindings; i++ ) {
  53. Size += sizeof(DWORD);
  54. if( BindingsInfo[i].Length != 0 ) {
  55. Size += ROUND_UP_COUNT(BindingsInfo[i].Length, ALIGN_DWORD);
  56. TcpsvcsDbgAssert( BindingsInfo[i].BindData != NULL );
  57. }
  58. }
  59. }
  60. return( Size );
  61. }
  62. VOID
  63. EMBED_SERVICE_INFO::CopyServiceInfo(
  64. LPINET_SERVICE_INFO ServiceInfo
  65. )
  66. /*++
  67. Routine Description:
  68. This private member function copies service info to the embedded service info buffer.
  69. Arguments:
  70. ServiceInfo : pointer to a service info structure.
  71. Return Value:
  72. NONE.
  73. --*/
  74. {
  75. DWORD NumBindings;
  76. LPINET_BIND_INFO BindingsInfo;
  77. DWORD i;
  78. LPBYTE EndofBuffer;
  79. LPBYTE BufferPtr;
  80. NumBindings = ServiceInfo->Bindings.NumBindings;
  81. BindingsInfo = ServiceInfo->Bindings.BindingsInfo;
  82. BufferPtr = _ServiceInfoBuffer;
  83. EndofBuffer = _ServiceInfoBuffer + _ServiceInfoLength;
  84. //
  85. // copy header.
  86. //
  87. *(ULONGLONG UNALIGNED *)BufferPtr = ServiceInfo->ServiceMask;
  88. _ServiceMask = (ULONGLONG UNALIGNED *)BufferPtr;
  89. BufferPtr += sizeof(ULONGLONG);
  90. *(INET_SERVICE_STATE *)BufferPtr = ServiceInfo->ServiceState;
  91. _ServiceState = (INET_SERVICE_STATE *)BufferPtr;
  92. BufferPtr += sizeof(INET_SERVICE_STATE);
  93. //
  94. // copy service comment.
  95. //
  96. DWORD CommentLen;
  97. if( ServiceInfo->ServiceComment != NULL) {
  98. CommentLen =
  99. ROUND_UP_COUNT(
  100. (strlen(ServiceInfo->ServiceComment) + 1) * sizeof(CHAR),
  101. ALIGN_DWORD);
  102. }
  103. else {
  104. CommentLen = ROUND_UP_COUNT( 1, ALIGN_DWORD );
  105. }
  106. TcpsvcsDbgAssert( (BufferPtr + CommentLen) < EndofBuffer );
  107. if( ServiceInfo->ServiceComment != NULL) {
  108. strcpy( (LPSTR)BufferPtr, ServiceInfo->ServiceComment );
  109. }
  110. else {
  111. *(LPSTR)BufferPtr = '\0';
  112. }
  113. BufferPtr += CommentLen;
  114. *(DWORD *)BufferPtr = ServiceInfo->Bindings.NumBindings;
  115. BufferPtr += sizeof(DWORD);
  116. //
  117. // copy bindings.
  118. //
  119. if( NumBindings != 0 ) {
  120. for( i = 0; i < NumBindings; i++ ) {
  121. TcpsvcsDbgAssert( BufferPtr < EndofBuffer );
  122. *(DWORD *)BufferPtr = BindingsInfo[i].Length;
  123. BufferPtr += sizeof(DWORD);
  124. if( BindingsInfo[i].Length != 0 ) {
  125. memcpy( BufferPtr, BindingsInfo[i].BindData, BindingsInfo[i].Length );
  126. BufferPtr += ROUND_UP_COUNT( BindingsInfo[i].Length, ALIGN_DWORD );
  127. }
  128. }
  129. }
  130. TcpsvcsDbgAssert( BufferPtr == EndofBuffer );
  131. return;
  132. }
  133. EMBED_SERVICE_INFO::EMBED_SERVICE_INFO(
  134. LPINET_SERVICE_INFO ServiceInfo
  135. )
  136. /*++
  137. Routine Description:
  138. This function constructs an embedded service info object.
  139. Note : embedded service info buffer layout :
  140. dword 1 : ServiceMask
  141. 2 : ServiceState
  142. 3 : NumBindings
  143. 4 : Binding1 Length
  144. 5 : Binding1
  145. 6 : ..
  146. 7 : ..
  147. 8 : ..
  148. 9 : Binding2 Length
  149. 10 : Binding2
  150. 11 : ..
  151. 12 : ..
  152. Arguments:
  153. ServiceInfo : pointer to a service info structure.
  154. Return Value:
  155. NONE.
  156. --*/
  157. {
  158. DWORD Size;
  159. //
  160. // initialize the object elements.
  161. //
  162. INITIALIZE_CRITICAL_SECTION( &_ServiceObjCritSect );
  163. _ServiceInfoLength = 0;
  164. _ServiceInfoBuffer = NULL;
  165. _AllottedBufferSize = 0;
  166. _ServiceState = NULL;
  167. _ServiceComment = NULL;
  168. _ServiceMask = NULL;
  169. TcpsvcsDbgAssert( ServiceInfo != NULL );
  170. if( ServiceInfo == NULL ) {
  171. _Status = ERROR_INVALID_PARAMETER;
  172. return;
  173. }
  174. //
  175. // compute the embedded buffer length.
  176. //
  177. Size = ComputeServiceInfoSize( ServiceInfo );
  178. TcpsvcsDbgAssert( Size != 0 );
  179. //
  180. // allocate memory.
  181. //
  182. _ServiceInfoBuffer = (LPBYTE) SvclocHeap->Alloc( Size );
  183. if( _ServiceInfoBuffer == NULL ) {
  184. _Status = ERROR_NOT_ENOUGH_MEMORY;
  185. return;
  186. }
  187. _ServiceInfoLength = Size;
  188. _AllottedBufferSize = Size;
  189. //
  190. // copy service info.
  191. //
  192. CopyServiceInfo( ServiceInfo );
  193. _Status = ERROR_SUCCESS;
  194. return;
  195. }
  196. EMBED_SERVICE_INFO::EMBED_SERVICE_INFO(
  197. LPBYTE InfoBuffer,
  198. DWORD InfoBufferLength
  199. )
  200. /*++
  201. Routine Description:
  202. This function constructs an embedded service info object from a given
  203. embedded buffer.
  204. Arguments:
  205. InfoBuffer : pointer to a embedded buffer.
  206. InfoBufferLength : length of the embedded buffer.
  207. Return Value:
  208. NONE.
  209. --*/
  210. {
  211. TcpsvcsDbgAssert( InfoBuffer != NULL );
  212. TcpsvcsDbgAssert( InfoBufferLength != 0 );
  213. INITIALIZE_CRITICAL_SECTION( &_ServiceObjCritSect );
  214. _ServiceInfoLength = InfoBufferLength;
  215. _ServiceInfoBuffer = InfoBuffer;
  216. _AllottedBufferSize = 0;
  217. _ServiceMask = (ULONGLONG UNALIGNED *)InfoBuffer;
  218. _ServiceState = (INET_SERVICE_STATE *)(InfoBuffer + sizeof(ULONGLONG));
  219. _ServiceComment = (LPSTR)
  220. (InfoBuffer +
  221. sizeof(ULONGLONG)
  222. sizeof(INET_SERVICE_STATE) );
  223. _Status = ERROR_SUCCESS;
  224. }
  225. EMBED_SERVICE_INFO::~EMBED_SERVICE_INFO(
  226. VOID
  227. )
  228. /*++
  229. Routine Description:
  230. This function destructs a embedded service info object.
  231. Arguments:
  232. NONE.
  233. Return Value:
  234. NONE.
  235. --*/
  236. {
  237. if( _AllottedBufferSize != 0 ) {
  238. TcpsvcsDbgAssert( _ServiceInfoBuffer != NULL );
  239. SvclocHeap->Free( _ServiceInfoBuffer );
  240. }
  241. #if DBG
  242. _ServiceInfoLength = 0;
  243. _ServiceInfoBuffer = NULL;
  244. _AllottedBufferSize = 0;
  245. _ServiceState = NULL;
  246. _ServiceComment = NULL;
  247. _ServiceMask = NULL;
  248. #endif // DBG
  249. DeleteCriticalSection( &_ServiceObjCritSect );
  250. _Status = ERROR_SUCCESS;
  251. return;
  252. }
  253. DWORD
  254. EMBED_SERVICE_INFO::SetServiceInfo(
  255. LPINET_SERVICE_INFO ServiceInfo
  256. )
  257. /*++
  258. Routine Description:
  259. This member function sets the new service info to the embedded service
  260. info buffer.
  261. Arguments:
  262. ServiceInfo : pointer to a service info structure.
  263. Return Value:
  264. Windows error code.
  265. --*/
  266. {
  267. DWORD Size;
  268. TcpsvcsDbgAssert( ServiceInfo != NULL );
  269. LockServiceObj();
  270. if( ServiceInfo == NULL ) {
  271. UnlockServiceObj();
  272. return( ERROR_INVALID_PARAMETER );
  273. }
  274. //
  275. // compute the size of the new service info buffer.
  276. //
  277. Size = ComputeServiceInfoSize( ServiceInfo ) ;
  278. TcpsvcsDbgAssert( Size != 0 );
  279. if( Size > _AllottedBufferSize ) {
  280. LPBYTE NewServiceInfoBuffer;
  281. //
  282. // free the old buffer and reallocate a new one.
  283. //
  284. NewServiceInfoBuffer = (LPBYTE) SvclocHeap->Alloc( Size );
  285. if( NewServiceInfoBuffer == NULL ) {
  286. UnlockServiceObj();
  287. return( ERROR_NOT_ENOUGH_MEMORY );
  288. }
  289. SvclocHeap->Free( _ServiceInfoBuffer );
  290. _ServiceInfoBuffer = NewServiceInfoBuffer;
  291. _AllottedBufferSize = Size;
  292. }
  293. _ServiceInfoLength = Size;
  294. //
  295. // now copy buffer.
  296. //
  297. CopyServiceInfo( ServiceInfo );
  298. UnlockServiceObj();
  299. return( ERROR_SUCCESS );
  300. }
  301. DWORD
  302. EMBED_SERVICE_INFO::GetServiceInfo(
  303. LPINET_SERVICE_INFO *ServiceInfo
  304. )
  305. /*++
  306. Routine Description:
  307. This member function allocates memory for service info structure and
  308. copies service info from embedded service info buffer.
  309. Arguments:
  310. ServiceInfo : pointer to a location where the server info structure
  311. pointer is returned. The caller should free the structure after
  312. use.
  313. Return Value:
  314. Windows error code.
  315. --*/
  316. {
  317. DWORD Error;
  318. LPBYTE BufferPtr = _ServiceInfoBuffer;
  319. LPBYTE EndBufferPtr = _ServiceInfoBuffer + _ServiceInfoLength;
  320. DWORD NumBindings;
  321. DWORD i;
  322. LPINET_SERVICE_INFO LocalServiceInfo = NULL;
  323. LockServiceObj();
  324. //
  325. // allocate memory for the service info structure.
  326. //
  327. LocalServiceInfo = (LPINET_SERVICE_INFO)
  328. SvclocHeap->Alloc( sizeof( INET_SERVICE_INFO ) );
  329. if( LocalServiceInfo == NULL ) {
  330. Error = ERROR_NOT_ENOUGH_MEMORY;
  331. goto Cleanup;
  332. }
  333. //
  334. // copy main structure first.
  335. //
  336. LocalServiceInfo->ServiceMask = *(ULONGLONG UNALIGNED *)BufferPtr;
  337. BufferPtr += sizeof(ULONGLONG);
  338. LocalServiceInfo->ServiceState = *(INET_SERVICE_STATE *)BufferPtr;
  339. BufferPtr += sizeof(INET_SERVICE_STATE);
  340. //
  341. // allocate memory for the service comment.
  342. //
  343. DWORD CommentLen;
  344. CommentLen =
  345. ROUND_UP_COUNT(
  346. (strlen((LPSTR)BufferPtr) + 1) * sizeof(CHAR),
  347. ALIGN_DWORD );
  348. LocalServiceInfo->ServiceComment = (LPSTR)
  349. SvclocHeap->Alloc( CommentLen );
  350. if( LocalServiceInfo->ServiceComment == NULL ) {
  351. Error = ERROR_NOT_ENOUGH_MEMORY;
  352. goto Cleanup;
  353. }
  354. //
  355. // copy service comment.
  356. //
  357. strcpy(
  358. LocalServiceInfo->ServiceComment,
  359. (LPSTR)BufferPtr );
  360. BufferPtr += CommentLen;
  361. NumBindings = *(DWORD *)BufferPtr;
  362. BufferPtr += sizeof(DWORD);
  363. LocalServiceInfo->Bindings.NumBindings = 0;
  364. LocalServiceInfo->Bindings.BindingsInfo = NULL;
  365. if( NumBindings != 0 ) {
  366. LPINET_BIND_INFO Bindings;
  367. //
  368. // allocate memory for bindingsinfo array.
  369. //
  370. Bindings = (LPINET_BIND_INFO)
  371. SvclocHeap->Alloc( sizeof( INET_BIND_INFO ) * NumBindings );
  372. if( Bindings == NULL ) {
  373. Error = ERROR_NOT_ENOUGH_MEMORY;
  374. goto Cleanup;
  375. }
  376. LocalServiceInfo->Bindings.BindingsInfo = Bindings;
  377. for( i = 0; i < NumBindings; i++ ) {
  378. LPBYTE BindData;
  379. TcpsvcsDbgAssert( BufferPtr < EndBufferPtr );
  380. Bindings[i].Length = *(DWORD *)BufferPtr;
  381. BufferPtr += sizeof(DWORD);
  382. //
  383. // allocate memory for the bind data.
  384. //
  385. BindData = (LPBYTE)SvclocHeap->Alloc( Bindings[i].Length );
  386. if( BindData == NULL ) {
  387. //
  388. // free the bindings structure memory only if NumBindings
  389. // is zero, otherwise it will be freed later on along
  390. // with some other memory blocks.
  391. //
  392. if( LocalServiceInfo->Bindings.NumBindings == 0 ) {
  393. if( LocalServiceInfo->Bindings.BindingsInfo != NULL ) {
  394. SvclocHeap->Free( LocalServiceInfo->Bindings.BindingsInfo );
  395. LocalServiceInfo->Bindings.BindingsInfo = NULL;
  396. }
  397. }
  398. Error = ERROR_NOT_ENOUGH_MEMORY;
  399. goto Cleanup;
  400. }
  401. //
  402. // copy bind data.
  403. //
  404. memcpy( BindData, BufferPtr, Bindings[i].Length );
  405. BufferPtr += ROUND_UP_COUNT( Bindings[i].Length, ALIGN_DWORD );
  406. //
  407. // successfully copied one more bind data.
  408. //
  409. Bindings[i].BindData = BindData;
  410. LocalServiceInfo->Bindings.NumBindings++;
  411. }
  412. }
  413. //
  414. // all done.
  415. //
  416. *ServiceInfo = LocalServiceInfo;
  417. LocalServiceInfo = NULL;
  418. Error = ERROR_SUCCESS;
  419. Cleanup:
  420. if( LocalServiceInfo != NULL ) {
  421. FreeServiceInfo( LocalServiceInfo );
  422. }
  423. UnlockServiceObj();
  424. return( Error );
  425. }
  426. /*---------------------------------------------------------------------*/
  427. BOOL
  428. EMBED_SERVER_INFO::IsServiceEntryExist(
  429. ULONGLONG ServiceMask,
  430. LPEMBED_SERVICE_ENTRY *ServiceEntry
  431. )
  432. /*++
  433. Routine Description:
  434. This private member function looks up a service entry in the service
  435. list.
  436. Arguments:
  437. ServiceMask : mask of the service to look at.
  438. ServiceEntry : pointer to location where the service entry pointer is
  439. returned if found.
  440. Return Value:
  441. TRUE : if the service entry is found in the service list.
  442. FALSE : otherwise.
  443. --*/
  444. {
  445. PLIST_ENTRY SList;
  446. LPEMBED_SERVICE_ENTRY SEntry;
  447. ULONGLONG SMask;
  448. //
  449. // Scan service list.
  450. //
  451. for( SList = _ServicesList.Flink; SList != &_ServicesList; SList = SList->Flink ) {
  452. SEntry = (LPEMBED_SERVICE_ENTRY)SList;
  453. //
  454. // Get Service Mask.
  455. //
  456. SMask = (SEntry->ServiceObject)->GetServiceMask();
  457. if( SMask == ServiceMask ) {
  458. //
  459. // found the service entry.
  460. //
  461. *ServiceEntry = SEntry;
  462. return( TRUE );
  463. }
  464. }
  465. return( FALSE );
  466. }
  467. EMBED_SERVER_INFO::EMBED_SERVER_INFO(
  468. WORD MajorVersion,
  469. WORD MinorVersion,
  470. LPSTR ServerName
  471. )
  472. /*++
  473. Routine Description:
  474. This member function constructs a server info object.
  475. Arguments:
  476. MajorVersion : major version number of the server software.
  477. MinorVersion : minor version number of the server software.
  478. ServerName : computer name of the server.
  479. Return Value:
  480. None.
  481. --*/
  482. {
  483. DWORD Size;
  484. LPBYTE BufferPtr;
  485. DWORD ServerNameLen;
  486. //
  487. // init object fields.
  488. //
  489. INITIALIZE_CRITICAL_SECTION( &_ServerObjCritSect );
  490. _ServerInfoLength = 0;
  491. _ServerInfoBuffer = NULL;
  492. _AllottedBufferSize = 0;
  493. _VersionNum = NULL;
  494. _ServerLoad = NULL;
  495. _ServicesMask = NULL;
  496. _ServerName = NULL;
  497. _NumServices = NULL;
  498. InitializeListHead( &_ServicesList );
  499. //
  500. // compute Server Info Size.
  501. //
  502. ServerNameLen = ROUND_UP_COUNT(
  503. (strlen(ServerName) + 1) * sizeof(CHAR),
  504. ALIGN_DWORD);
  505. Size = sizeof(INET_VERSION_NUM) + // for version number
  506. ServerNameLen + // for server name
  507. sizeof(DWORD) + // for load factor
  508. sizeof(ULONGLONG) + // for services mask.
  509. sizeof(DWORD); // for number of services.
  510. _ServerInfoBuffer = (LPBYTE)SvclocHeap->Alloc( Size );
  511. if( _ServerInfoBuffer == NULL ) {
  512. _Status = ERROR_NOT_ENOUGH_MEMORY;
  513. return;
  514. }
  515. _ServerInfoLength = Size;
  516. _AllottedBufferSize = Size;
  517. BufferPtr = _ServerInfoBuffer;
  518. ((INET_VERSION_NUM *)BufferPtr)->Version.Major = MajorVersion;
  519. ((INET_VERSION_NUM *)BufferPtr)->Version.Minor = MinorVersion;
  520. _VersionNum = (INET_VERSION_NUM *)BufferPtr;
  521. BufferPtr += sizeof(INET_VERSION_NUM);
  522. strcpy( (LPSTR)BufferPtr, ServerName );
  523. _ServerName = (LPSTR)BufferPtr;
  524. BufferPtr += ServerNameLen;
  525. *(DWORD *)BufferPtr = 0; // load factor
  526. _ServerLoad = (DWORD *)BufferPtr;
  527. BufferPtr += sizeof(DWORD);
  528. *(ULONGLONG UNALIGNED *)BufferPtr = 0; // services mask;
  529. _ServicesMask = (ULONGLONG UNALIGNED *)BufferPtr;
  530. BufferPtr += sizeof(ULONGLONG);
  531. *(DWORD *)BufferPtr = 0; // num services.
  532. _NumServices = (DWORD *)BufferPtr;
  533. BufferPtr += sizeof(DWORD);
  534. TcpsvcsDbgAssert( BufferPtr == (_ServerInfoBuffer + _ServerInfoLength) );
  535. _Status = ERROR_SUCCESS;
  536. return;
  537. }
  538. EMBED_SERVER_INFO::EMBED_SERVER_INFO(
  539. LPBYTE ResponseBuffer,
  540. DWORD ResponseBufferLength
  541. )
  542. /*++
  543. Routine Description:
  544. This member function constructs a server info object from embedded
  545. server info buffer (received from the server).
  546. Arguments:
  547. ResponseBuffer : pointer to the embedded server info buffer.
  548. ResponseBufferLength : length of the above buffer.
  549. Return Value:
  550. --*/
  551. {
  552. LPBYTE BufferPtr;
  553. DWORD ServerNameLen;
  554. DWORD nServices;
  555. DWORD i;
  556. INITIALIZE_CRITICAL_SECTION( &_ServerObjCritSect );
  557. //
  558. // set object fields.
  559. //
  560. BufferPtr = _ServerInfoBuffer = ResponseBuffer;
  561. _VersionNum = (INET_VERSION_NUM *)BufferPtr;
  562. BufferPtr += sizeof(INET_VERSION_NUM); // skip version number.
  563. _ServerName = (LPSTR)BufferPtr;
  564. ServerNameLen =
  565. ROUND_UP_COUNT(
  566. (strlen((LPSTR)BufferPtr) + 1) * sizeof(CHAR),
  567. ALIGN_DWORD);
  568. BufferPtr += ServerNameLen;
  569. _ServerLoad = (DWORD *)BufferPtr;
  570. BufferPtr += sizeof(DWORD);
  571. _ServicesMask = (ULONGLONG UNALIGNED *)BufferPtr;
  572. BufferPtr += sizeof(ULONGLONG);
  573. _NumServices = (DWORD *)BufferPtr;
  574. BufferPtr += sizeof(DWORD);
  575. _ServerInfoLength = BufferPtr - _ServerInfoBuffer;
  576. _AllottedBufferSize = 0;
  577. nServices = *_NumServices;
  578. InitializeListHead( &_ServicesList );
  579. //
  580. // now make service objects.
  581. //
  582. for( i = 0; i < nServices; i++) {
  583. DWORD ServiceBufferLength;
  584. LPSERVICE_OBJECT ServiceObject;
  585. DWORD ObjStatus;
  586. LPEMBED_SERVICE_ENTRY ServiceEntry;
  587. ServiceBufferLength = *(DWORD * )BufferPtr;
  588. BufferPtr += sizeof(DWORD);
  589. //
  590. // make another service object.
  591. //
  592. ServiceObject =
  593. new EMBED_SERVICE_INFO( BufferPtr, ServiceBufferLength );
  594. if( ServiceObject == NULL ) {
  595. _Status = ERROR_NOT_ENOUGH_MEMORY;
  596. return;
  597. }
  598. ObjStatus = ServiceObject->GetStatus();
  599. if( ObjStatus != ERROR_SUCCESS ) {
  600. _Status = ObjStatus;
  601. delete ServiceObject;
  602. return;
  603. }
  604. //
  605. // allocate space for a new service entry.
  606. //
  607. ServiceEntry = (LPEMBED_SERVICE_ENTRY)
  608. SvclocHeap->Alloc( sizeof(EMBED_SERVICE_ENTRY) );
  609. if( ServiceEntry == NULL ) {
  610. _Status = ERROR_NOT_ENOUGH_MEMORY;
  611. delete ServiceObject;
  612. return;
  613. }
  614. ServiceEntry->ServiceObject = ServiceObject;
  615. //
  616. // add this new entry to the list.
  617. //
  618. InsertTailList( &_ServicesList, &ServiceEntry->NextEntry );
  619. //
  620. // point to the next service record.
  621. //
  622. BufferPtr += ServiceBufferLength;
  623. }
  624. _Status = ERROR_SUCCESS;
  625. return;
  626. }
  627. EMBED_SERVER_INFO::~EMBED_SERVER_INFO(
  628. VOID
  629. )
  630. /*++
  631. Routine Description:
  632. This member function destructs a server info object.
  633. Arguments:
  634. NONE.
  635. Return Value:
  636. NONE.
  637. --*/
  638. {
  639. //
  640. // delete all service objects first.
  641. //
  642. while( !IsListEmpty( &_ServicesList ) ) {
  643. LPEMBED_SERVICE_ENTRY ServiceEntry;
  644. //
  645. // remove an entry from the tail of the list.
  646. //
  647. ServiceEntry =
  648. (LPEMBED_SERVICE_ENTRY)RemoveTailList( &_ServicesList );
  649. //
  650. // delete service object.
  651. //
  652. delete ServiceEntry->ServiceObject;
  653. //
  654. // free the entry memory.
  655. //
  656. SvclocHeap->Free( ServiceEntry );
  657. }
  658. //
  659. // free up server info buffer.
  660. //
  661. if( _AllottedBufferSize != 0 ) {
  662. TcpsvcsDbgAssert( _ServerInfoBuffer != NULL );
  663. SvclocHeap->Free( _ServerInfoBuffer );
  664. }
  665. #if DBG
  666. _ServerInfoLength = 0;
  667. _ServerInfoBuffer = NULL;
  668. _AllottedBufferSize = 0;
  669. _VersionNum = NULL;
  670. _ServerLoad = NULL;
  671. _ServicesMask = NULL;
  672. _ServerName = NULL;
  673. _NumServices = NULL;
  674. #endif // DBG
  675. DeleteCriticalSection( &_ServerObjCritSect );
  676. _Status = ERROR_SUCCESS;
  677. return;
  678. }
  679. DWORD
  680. EMBED_SERVER_INFO::AddService (
  681. LPINET_SERVICE_INFO ServiceInfo
  682. )
  683. /*++
  684. Routine Description:
  685. This member function adds or replaces a service info object to the
  686. server info object.
  687. Arguments:
  688. ServiceInfo : pointer to the service info structure.
  689. Return Value:
  690. Windows Error Code.
  691. --*/
  692. {
  693. DWORD Error;
  694. LPSERVICE_OBJECT ServiceObj;
  695. LPEMBED_SERVICE_ENTRY ServiceEntry = NULL;
  696. ULONGLONG SMask;
  697. LockServerObj();
  698. SMask = ServiceInfo->ServiceMask;
  699. if( IsServiceEntryExist( SMask, &ServiceEntry ) ) {
  700. //
  701. // this service already exists, so just update the content.
  702. //
  703. TcpsvcsDbgAssert( ServiceEntry != NULL );
  704. TcpsvcsDbgAssert( (*_ServicesMask & SMask) == SMask );
  705. //
  706. // set service info.
  707. //
  708. Error = (ServiceEntry->ServiceObject)->SetServiceInfo( ServiceInfo );
  709. UnlockServerObj();
  710. return( Error );
  711. }
  712. //
  713. // new entry.
  714. //
  715. TcpsvcsDbgAssert( (*_ServicesMask & SMask) == 0 );
  716. //
  717. // make a service object.
  718. //
  719. ServiceObj = new EMBED_SERVICE_INFO( ServiceInfo );
  720. if( ServiceObj == NULL ) {
  721. UnlockServerObj();
  722. return( ERROR_NOT_ENOUGH_MEMORY );
  723. }
  724. Error = ServiceObj->GetStatus();
  725. if( Error != ERROR_SUCCESS ) {
  726. delete ServiceObj;
  727. UnlockServerObj();
  728. return( Error );
  729. }
  730. //
  731. // allocate memory for the new service entry.
  732. //
  733. ServiceEntry = (LPEMBED_SERVICE_ENTRY)
  734. SvclocHeap->Alloc( sizeof(EMBED_SERVICE_ENTRY) );
  735. if( ServiceEntry == NULL ) {
  736. delete ServiceObj;
  737. UnlockServerObj();
  738. return( ERROR_NOT_ENOUGH_MEMORY );
  739. }
  740. ServiceEntry->ServiceObject = ServiceObj;
  741. //
  742. // Adjust parameters.
  743. //
  744. *_ServicesMask |= SMask;
  745. (*_NumServices)++;
  746. //
  747. // add this entry to the service list.
  748. //
  749. InsertTailList(&_ServicesList, &ServiceEntry->NextEntry);
  750. UnlockServerObj();
  751. return( ERROR_SUCCESS );
  752. }
  753. DWORD
  754. EMBED_SERVER_INFO::RemoveService(
  755. ULONGLONG SMask
  756. )
  757. /*++
  758. Routine Description:
  759. This member function removes a service info object from the server
  760. info object.
  761. Arguments:
  762. SMask : Service mask of the service to be removed from the
  763. server object.
  764. Return Value:
  765. Windows Error Code.
  766. --*/
  767. {
  768. LPEMBED_SERVICE_ENTRY ServiceEntry = NULL;
  769. LockServerObj();
  770. //
  771. // check the service is in the service list.
  772. //
  773. if( IsServiceEntryExist( SMask, &ServiceEntry ) == FALSE ) {
  774. TcpsvcsDbgAssert( (*_ServicesMask & SMask) == 0);
  775. UnlockServerObj();
  776. return( ERROR_SERVICE_NOT_FOUND );
  777. }
  778. TcpsvcsDbgAssert( ServiceEntry != NULL );
  779. TcpsvcsDbgAssert( *_ServicesMask & SMask );
  780. //
  781. // adjust parameters.
  782. //
  783. *_ServicesMask &= ~SMask;
  784. (*_NumServices)--;
  785. //
  786. // remove entry from list.
  787. //
  788. RemoveEntryList( &ServiceEntry->NextEntry );
  789. //
  790. // delete service object.
  791. //
  792. delete ServiceEntry->ServiceObject;
  793. //
  794. // free entry memory.
  795. //
  796. SvclocHeap->Free( ServiceEntry );
  797. UnlockServerObj();
  798. return( ERROR_SUCCESS );
  799. }
  800. DWORD
  801. EMBED_SERVER_INFO::SetServiceState(
  802. ULONGLONG SMask,
  803. INET_SERVICE_STATE ServiceState
  804. )
  805. /*++
  806. Routine Description:
  807. This member function sets the state of a service.
  808. Arguments:
  809. SMask : Service Mask of the service whose state to be set.
  810. ServiceState : New state of the service.
  811. Return Value:
  812. None.
  813. --*/
  814. {
  815. LPEMBED_SERVICE_ENTRY ServiceEntry = NULL;
  816. LockServerObj();
  817. //
  818. // check the service is in the service list.
  819. //
  820. if( IsServiceEntryExist( SMask, &ServiceEntry ) == FALSE ) {
  821. TcpsvcsDbgAssert( (*_ServicesMask & SMask) == 0);
  822. UnlockServerObj();
  823. return( ERROR_SERVICE_NOT_FOUND );
  824. }
  825. TcpsvcsDbgAssert( ServiceEntry != NULL );
  826. TcpsvcsDbgAssert( *_ServicesMask & SMask );
  827. //
  828. // set service state.
  829. //
  830. (ServiceEntry->ServiceObject)->SetServiceState( ServiceState );
  831. UnlockServerObj();
  832. return( ERROR_SUCCESS );
  833. }
  834. DWORD
  835. EMBED_SERVER_INFO::ComputeResponseLength(
  836. VOID
  837. )
  838. /*++
  839. Routine Description:
  840. This member function computes the length of the response message
  841. (containing server info and all services info in the embedded
  842. formatted) sent to a client.
  843. Arguments:
  844. None.
  845. Return Value:
  846. Length of the response.
  847. --*/
  848. {
  849. DWORD Size = 0;
  850. PLIST_ENTRY SList;
  851. LPEMBED_SERVICE_ENTRY SEntry;
  852. LockServerObj();
  853. //
  854. // Compute response length of the services.
  855. //
  856. for( SList = _ServicesList.Flink; SList != &_ServicesList; SList = SList->Flink ) {
  857. SEntry = (LPEMBED_SERVICE_ENTRY)SList;
  858. //
  859. // Get Service info buffer size.
  860. //
  861. Size += (SEntry->ServiceObject)->GetServiceInfoLength();
  862. Size += sizeof(DWORD); // for service length info itself.
  863. }
  864. //
  865. // server info size.
  866. //
  867. Size += _ServerInfoLength;
  868. UnlockServerObj();
  869. return( Size );
  870. }
  871. DWORD
  872. EMBED_SERVER_INFO::MakeResponseMessage(
  873. LPBYTE MessageBuffer,
  874. DWORD BufferLength
  875. )
  876. /*++
  877. Routine Description:
  878. This member function builds a response message sent to a client.
  879. Arguments:
  880. MessageBuffer : pointer to a buffer where the response message is
  881. built.
  882. BufferLength : length of the message.
  883. Return Value:
  884. Windows Error Code.
  885. --*/
  886. {
  887. LPBYTE BufferPtr = MessageBuffer;
  888. LPBYTE EndBufferPtr = MessageBuffer + BufferLength;
  889. LPEMBED_SERVICE_ENTRY SEntry;
  890. ULONGLONG SMask;
  891. DWORD Error;
  892. DWORD RequiredBufferLength;
  893. PLIST_ENTRY SList;
  894. LockServerObj();
  895. RequiredBufferLength = ComputeResponseLength();
  896. if( RequiredBufferLength > BufferLength ) {
  897. UnlockServerObj();
  898. return( ERROR_INSUFFICIENT_BUFFER );
  899. }
  900. //
  901. // copy server info first.
  902. //
  903. memcpy( BufferPtr, _ServerInfoBuffer, _ServerInfoLength );
  904. BufferPtr += _ServerInfoLength;
  905. //
  906. // copy all service info buffers.
  907. //
  908. for( SList = _ServicesList.Flink; SList != &_ServicesList; SList = SList->Flink ) {
  909. DWORD *_ServiceInfoLength;
  910. TcpsvcsDbgAssert( BufferPtr < EndBufferPtr );
  911. _ServiceInfoLength = (DWORD *)BufferPtr;
  912. BufferPtr += sizeof(DWORD);
  913. SEntry = (LPEMBED_SERVICE_ENTRY)SList;
  914. //
  915. // Get Service Mask.
  916. //
  917. Error = (SEntry->ServiceObject)->GetServiceInfoBuffer(
  918. BufferPtr,
  919. (EndBufferPtr - BufferPtr),
  920. _ServiceInfoLength );
  921. if( Error != ERROR_SUCCESS ) {
  922. UnlockServerObj();
  923. return( Error );
  924. }
  925. BufferPtr += *_ServiceInfoLength;
  926. }
  927. UnlockServerObj();
  928. return( ERROR_SUCCESS );
  929. }
  930. DWORD
  931. EMBED_SERVER_INFO::GetServerInfo(
  932. LPINET_SERVER_INFO *ServerInfo
  933. )
  934. /*++
  935. Routine Description:
  936. This member function retrieves the server info structure.
  937. Arguments:
  938. ServerInfo : pointer to a location where the pointer to the server
  939. info structure is returned. The member function allots memory for
  940. the structure, the caller should free the mmeory after use.
  941. Return Value:
  942. Windows Error Code.
  943. --*/
  944. {
  945. DWORD Error;
  946. LPINET_SERVER_INFO LocalServerInfo = NULL;
  947. LPINET_SERVICE_INFO *ServicesInfoArray = NULL;
  948. PLIST_ENTRY SList;
  949. DWORD i;
  950. LockServerObj();
  951. //
  952. // allocate memory for the server info structure.
  953. //
  954. LocalServerInfo = (LPINET_SERVER_INFO)SvclocHeap->Alloc(sizeof(INET_SERVER_INFO) );
  955. if( LocalServerInfo == NULL ) {
  956. Error = ERROR_NOT_ENOUGH_MEMORY;
  957. goto Cleanup;
  958. }
  959. //
  960. // initialize all fields.
  961. //
  962. memset( LocalServerInfo, 0x0, sizeof(INET_SERVER_INFO) );
  963. //
  964. // fill in the fields.
  965. //
  966. //
  967. // server info field is fill by some one else !!
  968. // leave it empty for now.
  969. //
  970. LocalServerInfo->ServerAddress.Length = 0;
  971. LocalServerInfo->ServerAddress.BindData = NULL;
  972. LocalServerInfo->VersionNum = *_VersionNum;
  973. //
  974. // alloc memory for the server name.
  975. //
  976. LocalServerInfo->ServerName = (LPSTR)
  977. SvclocHeap->Alloc( (strlen(_ServerName) + 1) * sizeof(CHAR) );
  978. if( LocalServerInfo->ServerName == NULL ) {
  979. Error = ERROR_NOT_ENOUGH_MEMORY;
  980. goto Cleanup;
  981. }
  982. strcpy( LocalServerInfo->ServerName, _ServerName );
  983. LocalServerInfo->LoadFactor = *_ServerLoad;
  984. LocalServerInfo->ServicesMask = *_ServicesMask;
  985. LocalServerInfo->Services.NumServices = 0;
  986. LocalServerInfo->Services.Services = NULL;
  987. //
  988. // allocate memory for the service struct. array pointers.
  989. //
  990. ServicesInfoArray = (LPINET_SERVICE_INFO *)
  991. SvclocHeap->Alloc( (*_NumServices) * sizeof(LPINET_SERVICE_INFO ) );
  992. if(ServicesInfoArray == NULL ) {
  993. Error = ERROR_NOT_ENOUGH_MEMORY;
  994. goto Cleanup;
  995. }
  996. memset( ServicesInfoArray, 0x0, (*_NumServices) * sizeof(LPINET_SERVICE_INFO) );
  997. //
  998. // now get services info.
  999. //
  1000. for ( SList = _ServicesList.Flink, i = 0;
  1001. (SList != &_ServicesList) && (i < *_NumServices);
  1002. SList = SList->Flink, i++ ) {
  1003. LPSERVICE_OBJECT SObj;
  1004. SObj = ((LPEMBED_SERVICE_ENTRY)SList)->ServiceObject;
  1005. Error = SObj->GetServiceInfo( &ServicesInfoArray[i] );
  1006. if( Error != ERROR_SUCCESS ) {
  1007. goto Cleanup;
  1008. }
  1009. }
  1010. TcpsvcsDbgAssert( i <= (*_NumServices) );
  1011. LocalServerInfo->Services.NumServices = i;
  1012. LocalServerInfo->Services.Services = ServicesInfoArray;
  1013. ServicesInfoArray = NULL;
  1014. *ServerInfo = LocalServerInfo;
  1015. LocalServerInfo = NULL;
  1016. Error = ERROR_SUCCESS;
  1017. Cleanup:
  1018. if( Error != ERROR_SUCCESS ) {
  1019. //
  1020. // Cleanup allotted data.
  1021. //
  1022. if( ServicesInfoArray != NULL ) {
  1023. for ( i = 0; i < (*_NumServices) && ServicesInfoArray[i] != NULL; i++) {
  1024. FreeServiceInfo( ServicesInfoArray[i] );
  1025. }
  1026. SvclocHeap->Free( ServicesInfoArray );
  1027. }
  1028. if( LocalServerInfo != NULL ) {
  1029. if( LocalServerInfo->ServerName != NULL ) {
  1030. SvclocHeap->Free( LocalServerInfo->ServerName );
  1031. }
  1032. SvclocHeap->Free( LocalServerInfo );
  1033. }
  1034. }
  1035. UnlockServerObj();
  1036. return( Error );
  1037. }