Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

682 lines
17 KiB

  1. /*++
  2. Copyright (c) 1991-1992 Microsoft Corporation
  3. Module Name:
  4. SrvInfo.c
  5. Abstract:
  6. This module contains support for the server get and set info APIs
  7. in the server service.
  8. Author:
  9. David Treadwell (davidtr) 7-Mar-1991
  10. Revision History:
  11. --*/
  12. #include "srvsvcp.h"
  13. #include "ssreg.h"
  14. #include <netlibnt.h>
  15. #include <tstr.h>
  16. #include <lmerr.h>
  17. NET_API_STATUS NET_API_FUNCTION
  18. NetrServerGetInfo (
  19. IN LPWSTR ServerName,
  20. IN DWORD Level,
  21. OUT LPSERVER_INFO InfoStruct
  22. )
  23. /*++
  24. Routine Description:
  25. This routine uses the server parameters stored in the server service
  26. to return the server information.
  27. Arguments:
  28. None.
  29. Return Value:
  30. NET_API_STATUS - NO_ERROR or reason for failure.
  31. --*/
  32. {
  33. ULONG outputBufferLength;
  34. NET_API_STATUS error;
  35. ACCESS_MASK desiredAccess;
  36. LPWSTR DomainName;
  37. PNAME_LIST_ENTRY service;
  38. PTRANSPORT_LIST_ENTRY transport;
  39. UCHAR serverNameBuf[ MAX_PATH ];
  40. UNICODE_STRING ServerNameUnicode;
  41. NTSTATUS status;
  42. ULONG namelen;
  43. //
  44. // validate incomming string lengths
  45. //
  46. if(ServerName!=NULL && StringCchLength(ServerName,1024,NULL) != S_OK) {
  47. return ERROR_INVALID_PARAMETER;
  48. }
  49. //
  50. // Determine the access required for the requested level of
  51. // information.
  52. //
  53. switch ( Level ) {
  54. case 100:
  55. case 101:
  56. desiredAccess = SRVSVC_CONFIG_USER_INFO_GET;
  57. break;
  58. case 102:
  59. case 502:
  60. desiredAccess = SRVSVC_CONFIG_POWER_INFO_GET;
  61. break;
  62. case 503:
  63. desiredAccess = SRVSVC_CONFIG_ADMIN_INFO_GET;
  64. break;
  65. default:
  66. return ERROR_INVALID_LEVEL;
  67. }
  68. //
  69. // Make sure that the caller has that level of access.
  70. //
  71. error = SsCheckAccess(
  72. &SsConfigInfoSecurityObject,
  73. desiredAccess
  74. );
  75. if ( error != NO_ERROR ) {
  76. return ERROR_ACCESS_DENIED;
  77. }
  78. //
  79. // Acquire the resource that protects server information. Since
  80. // we'll only read the information, get shared access to the
  81. // resource.
  82. //
  83. (VOID)RtlAcquireResourceShared( &SsData.SsServerInfoResource, TRUE );
  84. if( ServerName == NULL ) {
  85. ServerName = SsData.ServerNameBuffer;
  86. }
  87. //
  88. // Convert the server name
  89. //
  90. if( ServerName[0] == L'\\' && ServerName[1] == L'\\' ) {
  91. ServerName += 2;
  92. }
  93. RtlInitUnicodeString( &ServerNameUnicode, ServerName );
  94. error = ConvertStringToTransportAddress( &ServerNameUnicode, serverNameBuf, &namelen );
  95. if( error != NERR_Success ) {
  96. RtlReleaseResource( &SsData.SsServerInfoResource );
  97. return error;
  98. }
  99. //
  100. // Look for the NAME_LIST_ENTRY entry that represents the name of the server
  101. // the client referred to.
  102. //
  103. DomainName = SsData.DomainNameBuffer;
  104. for( service = SsData.SsServerNameList; service != NULL; service = service->Next ) {
  105. if( service->TransportAddressLength != namelen ) {
  106. continue;
  107. }
  108. if( RtlEqualMemory( serverNameBuf, service->TransportAddress, namelen ) ) {
  109. DomainName = service->DomainName;
  110. break;
  111. }
  112. }
  113. //
  114. // If we didn't find an entry, find and use the primary entry
  115. //
  116. if( service == NULL ) {
  117. for( service = SsData.SsServerNameList; service != NULL; service = service->Next ) {
  118. if( service->PrimaryName ) {
  119. DomainName = service->DomainName;
  120. break;
  121. }
  122. }
  123. }
  124. //
  125. // Use the level parameter to determine how much space to allocate
  126. // and how to fill it in.
  127. //
  128. switch ( Level ) {
  129. case 100: {
  130. PSERVER_INFO_100 sv100;
  131. //
  132. // All we copy is the server name.
  133. //
  134. outputBufferLength = sizeof(SERVER_INFO_100) +
  135. STRSIZE( ServerName);
  136. sv100 = MIDL_user_allocate( outputBufferLength );
  137. if ( sv100 == NULL ) {
  138. RtlReleaseResource( &SsData.SsServerInfoResource );
  139. return ERROR_NOT_ENOUGH_MEMORY;
  140. }
  141. //
  142. // Copy over the fixed portion of the buffer.
  143. //
  144. RtlCopyMemory( sv100, &SsData.ServerInfo102, sizeof(SERVER_INFO_100) );
  145. //
  146. // Set up the name string.
  147. //
  148. sv100->sv100_name = (LPWSTR)( sv100 + 1 );
  149. STRCPY( sv100->sv100_name, ServerName );
  150. //
  151. // Set up the output buffer pointer.
  152. //
  153. InfoStruct->ServerInfo100 = sv100;
  154. break;
  155. }
  156. case 101: {
  157. PSERVER_INFO_101 sv101;
  158. //
  159. // All we copy is the server name.
  160. //
  161. outputBufferLength = sizeof(SERVER_INFO_101) +
  162. STRSIZE( ServerName ) +
  163. STRSIZE( SsData.ServerCommentBuffer ) ;
  164. sv101 = MIDL_user_allocate( outputBufferLength );
  165. if ( sv101 == NULL ) {
  166. RtlReleaseResource( &SsData.SsServerInfoResource );
  167. return ERROR_NOT_ENOUGH_MEMORY;
  168. }
  169. //
  170. // Copy over the fixed portion of the buffer.
  171. //
  172. RtlCopyMemory( sv101, &SsData.ServerInfo102, sizeof(SERVER_INFO_101) );
  173. if( service != NULL ) {
  174. sv101->sv101_type = service->ServiceBits;
  175. for( transport = service->Transports; transport; transport = transport->Next ) {
  176. sv101->sv101_type |= transport->ServiceBits;
  177. }
  178. } else {
  179. //
  180. // If there are no transports,
  181. // return the global information.
  182. //
  183. sv101->sv101_type = SsGetServerType();
  184. }
  185. //
  186. // Set up the variable portion of the buffer.
  187. //
  188. sv101->sv101_name = (LPWSTR)( sv101 + 1 );
  189. STRCPY( sv101->sv101_name, ServerName );
  190. sv101->sv101_comment = (LPWSTR)( (PCHAR)sv101->sv101_name +
  191. STRSIZE( ServerName ));
  192. STRCPY( sv101->sv101_comment, SsData.ServerCommentBuffer );
  193. //
  194. // Set up the output buffer pointer.
  195. //
  196. InfoStruct->ServerInfo101 = sv101;
  197. break;
  198. }
  199. case 102: {
  200. PSERVER_INFO_102 sv102;
  201. //
  202. // We copy the server name, server comment, and user path
  203. // buffer.
  204. //
  205. outputBufferLength = sizeof(SERVER_INFO_102) +
  206. STRSIZE( ServerName ) +
  207. STRSIZE( SsData.ServerCommentBuffer ) +
  208. STRSIZE( SsData.UserPathBuffer ) ;
  209. sv102 = MIDL_user_allocate( outputBufferLength );
  210. if ( sv102 == NULL ) {
  211. RtlReleaseResource( &SsData.SsServerInfoResource );
  212. return ERROR_NOT_ENOUGH_MEMORY;
  213. }
  214. //
  215. // Copy over the fixed portion of the buffer.
  216. //
  217. RtlCopyMemory( sv102, &SsData.ServerInfo102, sizeof(SERVER_INFO_102) );
  218. if( service != NULL ) {
  219. sv102->sv102_type = service->ServiceBits;
  220. for( transport = service->Transports; transport; transport = transport->Next ) {
  221. sv102->sv102_type |= transport->ServiceBits;
  222. }
  223. } else {
  224. //
  225. // If there are no transports,
  226. // return the global information.
  227. //
  228. sv102->sv102_type = SsGetServerType();
  229. }
  230. //
  231. // Set up the server name.
  232. //
  233. sv102->sv102_name = (LPWSTR)( sv102 + 1 );
  234. STRCPY( sv102->sv102_name, ServerName );
  235. //
  236. // Set up the server comment.
  237. //
  238. sv102->sv102_comment = (LPWSTR)( (PCHAR)sv102->sv102_name + STRSIZE( ServerName ));
  239. STRCPY( sv102->sv102_comment, SsData.ServerCommentBuffer );
  240. //
  241. // Set up the user path.
  242. //
  243. sv102->sv102_userpath = (LPWSTR)( (PCHAR)sv102->sv102_comment +
  244. STRSIZE( sv102->sv102_comment ) );
  245. STRCPY( sv102->sv102_userpath, SsData.UserPathBuffer );
  246. //
  247. // Set up the output buffer pointer.
  248. //
  249. InfoStruct->ServerInfo102 = sv102;
  250. break;
  251. }
  252. case 502:
  253. //
  254. // Allocate enough space to hold the fixed structure. This level has
  255. // no variable structure.
  256. //
  257. InfoStruct->ServerInfo502 = MIDL_user_allocate( sizeof(SERVER_INFO_502) );
  258. if ( InfoStruct->ServerInfo502 == NULL ) {
  259. RtlReleaseResource( &SsData.SsServerInfoResource );
  260. return ERROR_NOT_ENOUGH_MEMORY;
  261. }
  262. //
  263. // Copy the data from the server service buffer to the user buffer.
  264. //
  265. RtlCopyMemory(
  266. InfoStruct->ServerInfo502,
  267. &SsData.ServerInfo599,
  268. sizeof(SERVER_INFO_502)
  269. );
  270. break;
  271. case 503: {
  272. PSERVER_INFO_503 sv503;
  273. outputBufferLength = sizeof( *sv503 ) + STRSIZE( DomainName );
  274. sv503 = MIDL_user_allocate( outputBufferLength );
  275. if ( sv503 == NULL ) {
  276. RtlReleaseResource( &SsData.SsServerInfoResource );
  277. return ERROR_NOT_ENOUGH_MEMORY;
  278. }
  279. //
  280. // Copy the data from the server service buffer to the user buffer.
  281. //
  282. RtlCopyMemory( sv503, &SsData.ServerInfo599, sizeof( *sv503 ) );
  283. //
  284. // Copy the domain name
  285. //
  286. sv503->sv503_domain = (LPWSTR)( sv503 + 1 );
  287. STRCPY( sv503->sv503_domain, DomainName );
  288. InfoStruct->ServerInfo503 = sv503;
  289. break;
  290. }
  291. default:
  292. RtlReleaseResource( &SsData.SsServerInfoResource );
  293. return ERROR_INVALID_LEVEL;
  294. }
  295. RtlReleaseResource( &SsData.SsServerInfoResource );
  296. return NO_ERROR;
  297. } // NetrServerGetInfo
  298. NET_API_STATUS NET_API_FUNCTION
  299. NetrServerSetInfo (
  300. IN LPWSTR ServerName,
  301. IN DWORD Level,
  302. IN LPSERVER_INFO InfoStruct,
  303. OUT LPDWORD ErrorParameter OPTIONAL
  304. )
  305. /*++
  306. Routine Description:
  307. This routine sets information in the server service and server.
  308. Arguments:
  309. None.
  310. Return Value:
  311. NET_API_STATUS - NO_ERROR or reason for failure.
  312. --*/
  313. {
  314. NET_API_STATUS error;
  315. ULONG i;
  316. LONG parmnum;
  317. BOOLEAN validLevel = FALSE;
  318. PSERVER_REQUEST_PACKET srp;
  319. LPBYTE buffer = (LPBYTE)InfoStruct->ServerInfo100;
  320. BOOLEAN announcementInformationChanged = FALSE;
  321. ServerName;
  322. //
  323. // Check that user input buffer is not NULL
  324. //
  325. if (buffer == NULL) {
  326. if ( ARGUMENT_PRESENT( ErrorParameter ) ) {
  327. *ErrorParameter = PARM_ERROR_UNKNOWN;
  328. }
  329. return ERROR_INVALID_PARAMETER;
  330. }
  331. parmnum = (LONG)(Level - PARMNUM_BASE_INFOLEVEL);
  332. if ( ARGUMENT_PRESENT( ErrorParameter ) ) {
  333. *ErrorParameter = parmnum;
  334. }
  335. //
  336. // Make sure that the caller is allowed to set information in the
  337. // server.
  338. //
  339. error = SsCheckAccess(
  340. &SsConfigInfoSecurityObject,
  341. SRVSVC_CONFIG_INFO_SET
  342. );
  343. if ( error != NO_ERROR ) {
  344. return ERROR_ACCESS_DENIED;
  345. }
  346. //
  347. // Acquire the resource that protects server information. Since
  348. // we're going to be writing to the information, we need exclusive
  349. // access to the reqource.
  350. //
  351. //
  352. // If a parameter number was specified, set that one field.
  353. //
  354. if ( parmnum >= 0 ) {
  355. //
  356. // Walk through the field descriptors looking for an
  357. // equivalent parameter number.
  358. //
  359. for ( i = 0; SsServerInfoFields[i].FieldName != NULL; i++ ) {
  360. if ( (ULONG)parmnum == SsServerInfoFields[i].ParameterNumber ) {
  361. //
  362. // Verify that the field is settable.
  363. //
  364. // !!! We should also reject levels above 502?
  365. //
  366. if ( SsServerInfoFields[i].Settable != ALWAYS_SETTABLE ) {
  367. return ERROR_INVALID_LEVEL;
  368. }
  369. (VOID)RtlAcquireResourceExclusive( &SsData.SsServerInfoResource, TRUE );
  370. //
  371. // Set the field.
  372. //
  373. error = SsSetField(
  374. &SsServerInfoFields[i],
  375. buffer,
  376. TRUE,
  377. &announcementInformationChanged
  378. );
  379. RtlReleaseResource( &SsData.SsServerInfoResource );
  380. //
  381. // If a relevant parameter changed, call
  382. // SsSetExportedServerType. This will cause an
  383. // announcement to be sent.
  384. //
  385. if ( announcementInformationChanged ) {
  386. SsSetExportedServerType( NULL, TRUE, TRUE );
  387. }
  388. return error;
  389. }
  390. }
  391. //
  392. // If a match had been found we would have returned by now.
  393. // Indicate that the parameter number was illegal.
  394. //
  395. return ERROR_INVALID_LEVEL;
  396. }
  397. //
  398. // A full input structure was specified. Walk through all the
  399. // server data field descriptors, looking for fields that should be
  400. // set.
  401. //
  402. for ( i = 0; SsServerInfoFields[i].FieldName != NULL; i++ ) {
  403. ULONG fieldLevel;
  404. //
  405. // We need to set this field if:
  406. //
  407. // o the level specified on input is the same order as the
  408. // level of the field. They have the same order if
  409. // they are in the same century (e.g. 101 and 102 are
  410. // in the same order); AND
  411. //
  412. // o the specified level is greater than or equal to the
  413. // level of the field. For example, if the input
  414. // level is 101 and the field level is 102, don't set
  415. // the field. If the input level is 102 and the field
  416. // level is 101, set it; AND
  417. //
  418. // o the field is settable. If the field is not settable
  419. // by NetServerSetInfo, just ignore the value in the
  420. // input structure.
  421. //
  422. // Note that level 598 doesn't follow the first rule above. It
  423. // is NOT a superset of 50x, and it is NOT a subset of 599.
  424. //
  425. fieldLevel = SsServerInfoFields[i].Level;
  426. if ( Level / 100 == fieldLevel / 100 &&
  427. ((fieldLevel != 598) && (Level >= fieldLevel) ||
  428. (fieldLevel == 598) && (Level == 598)) &&
  429. SsServerInfoFields[i].Settable == ALWAYS_SETTABLE ) {
  430. //
  431. // We found a match, so the specified level number must have
  432. // been valid.
  433. //
  434. // !!! Reject levels above 502?
  435. validLevel = TRUE;
  436. //
  437. // Set this field.
  438. //
  439. (VOID)RtlAcquireResourceExclusive( &SsData.SsServerInfoResource, TRUE );
  440. error = SsSetField(
  441. &SsServerInfoFields[i],
  442. buffer + SsServerInfoFields[i].FieldOffset,
  443. TRUE,
  444. &announcementInformationChanged
  445. );
  446. RtlReleaseResource( &SsData.SsServerInfoResource );
  447. if ( error != NO_ERROR ) {
  448. //
  449. // Set the parameter in error if we need to.
  450. //
  451. if ( ARGUMENT_PRESENT(ErrorParameter) ) {
  452. *ErrorParameter = SsServerInfoFields[i].ParameterNumber;
  453. }
  454. return error;
  455. }
  456. }
  457. }
  458. //
  459. // If no match was ever found, then an invalid level was passed in.
  460. //
  461. if ( !validLevel ) {
  462. return ERROR_INVALID_LEVEL;
  463. }
  464. //
  465. // Get an SRP and set it up with the appropriate level.
  466. //
  467. srp = SsAllocateSrp( );
  468. if ( srp == NULL ) {
  469. return ERROR_NOT_ENOUGH_MEMORY;
  470. }
  471. srp->Level = 0xFFFFFFFF;
  472. (VOID)RtlAcquireResourceShared( &SsData.SsServerInfoResource, TRUE );
  473. //
  474. // Send the request on to the server.
  475. //
  476. error = SsServerFsControl(
  477. FSCTL_SRV_NET_SERVER_SET_INFO,
  478. srp,
  479. &SsData.ServerInfo102,
  480. sizeof(SERVER_INFO_102) + sizeof(SERVER_INFO_599) +
  481. sizeof(SERVER_INFO_598)
  482. );
  483. //
  484. // Release the resource and free the SRP.
  485. //
  486. RtlReleaseResource( &SsData.SsServerInfoResource );
  487. SsFreeSrp( srp );
  488. //
  489. // If a relevant parameter changed, call SsSetExportedServerType.
  490. // This will cause an announcement to be sent.
  491. //
  492. if ( announcementInformationChanged ) {
  493. SsSetExportedServerType( NULL, TRUE, TRUE );
  494. }
  495. return error;
  496. } // NetrServerSetInfo