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.

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