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.

1336 lines
39 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. stub.c
  5. Abstract:
  6. Domain Name System (DNS) Server -- Admin Client API
  7. Client stubs for DNS API.
  8. These are stubs for NT5+ API. NT4 API stubs are in nt4stub.c.
  9. Author:
  10. Jim Gilroy (jamesg) April 1997
  11. Environment:
  12. User Mode - Win32
  13. Revision History:
  14. --*/
  15. #include "dnsclip.h"
  16. #if DBG
  17. #define DBG_FN( funcName ) static const char * fn = (funcName);
  18. #else
  19. #define DBG_FN( funcName )
  20. #endif
  21. //
  22. // For versioning, we use a simple state machine in each function's
  23. // RPC exception block to try the new RPC call then the old RPC call.
  24. // If there is any RPC error, retry a downlevel operation.
  25. //
  26. // This macro'ing is a bit overkill, but each RPC interface wrapper
  27. // needs this retry logic.
  28. //
  29. #define DNS_RPC_RETRY_STATE() iDnsRpcRetryState
  30. #define DECLARE_DNS_RPC_RETRY_STATE() INT DNS_RPC_RETRY_STATE() = 0
  31. #define DECLARE_DNS_RPC_RETRY_LABEL() DnsRpcRetryLabel:
  32. #define ADVANCE_DNS_RPC_RETRY_STATE( dwStatus ) \
  33. if ( DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_NEW && \
  34. ( dwStatus == ERROR_SUCCESS || \
  35. dwStatus < RPC_S_INVALID_STRING_BINDING || \
  36. dwStatus > RPC_X_BAD_STUB_DATA ) ) \
  37. DNS_RPC_RETRY_STATE() = DNS_RPC_TRY_DONE; \
  38. else \
  39. ++DNS_RPC_RETRY_STATE();
  40. #define TEST_DNS_RPC_RETRY() \
  41. if ( DNS_RPC_RETRY_STATE() < DNS_RPC_TRY_DONE ) { goto DnsRpcRetryLabel; }
  42. #define ASSERT_DNS_RPC_RETRY_STATE_VALID() \
  43. ASSERT( DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_NEW || \
  44. DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_OLD )
  45. #define DNS_RPC_TRY_NEW 0
  46. #define DNS_RPC_TRY_OLD 1
  47. #define DNS_RPC_TRY_DONE 2
  48. //
  49. // This macro is a safety helper for use in DnsRpc_ConvertToCurrent.
  50. //
  51. // If header definitions change, DnsRpc_ConvertToCurrent can
  52. // start doing wacky things. Using memcpy instead of individual
  53. // assignments saves instructions but is potentially dangerous if
  54. // headers change and this function is not updated. Add ASSERTS
  55. // where possible to try and catch header changes that have not
  56. // been accounted for here. A general principal is that a structure
  57. // may grow but not shrink in size between versions.
  58. //
  59. #if DBG
  60. #define DNS_ASSERT_CURRENT_LARGER( structName ) \
  61. ASSERT( sizeof( DNS_RPC_##structName##_WHISTLER ) >= \
  62. sizeof( DNS_RPC_##structName##_W2K ) );
  63. #define DNS_ASSERT_RPC_STRUCTS_ARE_SANE() \
  64. { \
  65. static LONG finit = 0; \
  66. \
  67. if ( InterlockedIncrement( &finit ) != 1 ) \
  68. { \
  69. goto DoneDbgAsserts; \
  70. } \
  71. \
  72. DNS_ASSERT_CURRENT_LARGER( SERVER_INFO ); \
  73. DNS_ASSERT_CURRENT_LARGER( FORWARDERS ); \
  74. DNS_ASSERT_CURRENT_LARGER( ZONE ); \
  75. DNS_ASSERT_CURRENT_LARGER( ZONE_INFO ); \
  76. DNS_ASSERT_CURRENT_LARGER( ZONE_SECONDARIES ); \
  77. DNS_ASSERT_CURRENT_LARGER( ZONE_DATABASE ); \
  78. DNS_ASSERT_CURRENT_LARGER( ZONE_TYPE_RESET ); \
  79. DNS_ASSERT_CURRENT_LARGER( ZONE_CREATE_INFO ); \
  80. DNS_ASSERT_CURRENT_LARGER( ZONE_LIST ); \
  81. DNS_ASSERT_CURRENT_LARGER( SERVER_INFO ); \
  82. DNS_ASSERT_CURRENT_LARGER( FORWARDERS ); \
  83. DNS_ASSERT_CURRENT_LARGER( ZONE ); \
  84. DNS_ASSERT_CURRENT_LARGER( ZONE_SECONDARIES ); \
  85. DNS_ASSERT_CURRENT_LARGER( ZONE_DATABASE ); \
  86. DNS_ASSERT_CURRENT_LARGER( ZONE_TYPE_RESET ); \
  87. DNS_ASSERT_CURRENT_LARGER( ZONE_LIST ); \
  88. \
  89. DoneDbgAsserts: ; \
  90. }
  91. #else
  92. #define DNS_ASSERT_RPC_STRUCTS_ARE_SANE()
  93. #endif // DBG
  94. DNS_STATUS
  95. DNS_API_FUNCTION
  96. DnsRpc_ConvertToCurrent(
  97. IN PDWORD pdwTypeId, IN OUT
  98. IN PVOID * ppData IN OUT
  99. )
  100. /*++
  101. Routine Description:
  102. Takes any DNS RPC structure as input and if necessary fabricates
  103. the latest revision of that structure from the members of the input
  104. structure.
  105. If a new structure is allocated, the old one is freed and the pointer
  106. value at ppData is replaced. Allocated points within the old struct
  107. will be freed or copied to the new struct. Basically, the client
  108. does not have to worry about freeing any part of the old struct. When
  109. he's done with the new struct he has to free it and it's members, as
  110. usual.
  111. There are two main uses of this function:
  112. - If an old client sends the DNS server an input structure, such as
  113. ZONE_CREATE, the new DNS server can use this function to update
  114. the structure so that it can be processed.
  115. - If an old server sends the DNS RPC client an output structure, such
  116. as SERVER_INFO, the new DNS RPC client can use this function to
  117. update the structure so that it can be processed.
  118. Arguments:
  119. pdwTypeId - type ID of object pointed to by ppData, value may be
  120. changed to type ID of new object at ppData
  121. ppData - pointer to object, pointer may be replaced by a pointer to
  122. a newly allocated, completed different structure as required
  123. Return Value:
  124. ERROR_SUCCESS or error code. If return code is not ERROR_SUCCESS, there
  125. has been some kind of fatal error. Assume data invalid in this case.
  126. --*/
  127. {
  128. DBG_FN( "DnsRpc_ConvertToCurrent" )
  129. DNS_STATUS status = ERROR_SUCCESS;
  130. DWORD dwtypeIn = -1;
  131. PVOID pdataIn = NULL;
  132. DWORD dwtypeOut = -1;
  133. PVOID pdataOut = NULL;
  134. DWORD i;
  135. if ( !pdwTypeId || !ppData )
  136. {
  137. ASSERT( pdwTypeId && ppData );
  138. status = ERROR_INVALID_DATA;
  139. goto NoTranslation;
  140. }
  141. //
  142. // Shortcuts: do not translate NULL or certain common types.
  143. //
  144. if ( *pdwTypeId < DNSSRV_TYPEID_SERVER_INFO_W2K || *ppData == NULL )
  145. {
  146. goto NoTranslation;
  147. }
  148. dwtypeOut = dwtypeIn = *pdwTypeId;
  149. pdataOut = pdataIn = *ppData;
  150. DNS_ASSERT_RPC_STRUCTS_ARE_SANE();
  151. //
  152. // Handy macros to make allocating the differently sized structs easy.
  153. //
  154. #define ALLOCATE_RPC_BYTES( ptr, byteCount ) \
  155. ptr = MIDL_user_allocate( byteCount ); \
  156. if ( ptr == NULL ) \
  157. { \
  158. status = DNS_ERROR_NO_MEMORY; \
  159. goto Done; \
  160. } \
  161. RtlZeroMemory( ptr, byteCount );
  162. #define ALLOCATE_RPC_STRUCT( ptr, structType ) \
  163. ALLOCATE_RPC_BYTES( ptr, sizeof( structType ) );
  164. #define DNS_WHISTLER_VERSION_SIZE ( 2 * sizeof( DWORD ) )
  165. //
  166. // Giant switch statement of all types that are no longer current.
  167. //
  168. // Add to this switch as we create more versions of types. The idea
  169. // is to convert any structure from an old server to the
  170. // corresponding current version so that the RPC client doesn't
  171. // have to worry about multiple versions of the structures.
  172. //
  173. switch ( dwtypeIn )
  174. {
  175. case DNSSRV_TYPEID_SERVER_INFO_W2K:
  176. //
  177. // Structures are identical except for dwRpcStuctureVersion
  178. // and some usage in Whistler of reserved W2K fields. No
  179. // need to be concerned about the newly used reserved, they
  180. // will be NULL in the W2K structure.
  181. //
  182. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_SERVER_INFO_WHISTLER );
  183. RtlCopyMemory(
  184. ( PBYTE ) pdataOut + DNS_WHISTLER_VERSION_SIZE,
  185. pdataIn,
  186. sizeof( DNS_RPC_SERVER_INFO_W2K ) );
  187. ( ( PDNS_RPC_SERVER_INFO_WHISTLER ) pdataOut )->
  188. dwRpcStuctureVersion = DNS_RPC_SERVER_INFO_VER;
  189. dwtypeOut = DNSSRV_TYPEID_SERVER_INFO;
  190. break;
  191. case DNSSRV_TYPEID_FORWARDERS_W2K:
  192. //
  193. // Structures are identical except for dwRpcStuctureVersion.
  194. //
  195. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_FORWARDERS_WHISTLER );
  196. RtlCopyMemory(
  197. ( PBYTE ) pdataOut + DNS_WHISTLER_VERSION_SIZE,
  198. pdataIn,
  199. sizeof( DNS_RPC_FORWARDERS_W2K ) );
  200. ( ( PDNS_RPC_FORWARDERS_WHISTLER ) pdataOut )->
  201. dwRpcStuctureVersion = DNS_RPC_FORWARDERS_VER;
  202. dwtypeOut = DNSSRV_TYPEID_FORWARDERS;
  203. break;
  204. case DNSSRV_TYPEID_ZONE_W2K:
  205. //
  206. // Structures are identical except for dwRpcStuctureVersion.
  207. //
  208. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_WHISTLER );
  209. RtlCopyMemory(
  210. ( PBYTE ) pdataOut + DNS_WHISTLER_VERSION_SIZE,
  211. pdataIn,
  212. sizeof( DNS_RPC_ZONE_W2K ) );
  213. ( ( PDNS_RPC_ZONE_WHISTLER ) pdataOut )->
  214. dwRpcStuctureVersion = DNS_RPC_ZONE_VER;
  215. dwtypeOut = DNSSRV_TYPEID_ZONE;
  216. break;
  217. case DNSSRV_TYPEID_ZONE_INFO_W2K:
  218. //
  219. // Whistler structure is larger and has new fields for
  220. // forwarder zones, stub zones, directory partitions, etc.
  221. // The structures are identical up to the beginning of
  222. // the reserved DWORDs at the end of the W2K structure.
  223. //
  224. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_INFO_WHISTLER );
  225. RtlZeroMemory( pdataOut, sizeof( DNS_RPC_ZONE_INFO_WHISTLER ) );
  226. RtlCopyMemory(
  227. ( PBYTE ) pdataOut + DNS_WHISTLER_VERSION_SIZE,
  228. pdataIn,
  229. sizeof( DNS_RPC_ZONE_INFO_W2K ) );
  230. ( ( PDNS_RPC_ZONE_INFO_WHISTLER ) pdataOut )->
  231. dwRpcStuctureVersion = DNS_RPC_ZONE_VER;
  232. dwtypeOut = DNSSRV_TYPEID_ZONE_INFO;
  233. break;
  234. case DNSSRV_TYPEID_ZONE_SECONDARIES_W2K:
  235. //
  236. // Structures are identical except for dwRpcStuctureVersion.
  237. //
  238. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_SECONDARIES_WHISTLER );
  239. RtlCopyMemory(
  240. ( PBYTE ) pdataOut + DNS_WHISTLER_VERSION_SIZE,
  241. pdataIn,
  242. sizeof( DNS_RPC_ZONE_SECONDARIES_W2K ) );
  243. ( ( PDNS_RPC_ZONE_SECONDARIES_WHISTLER ) pdataOut )->
  244. dwRpcStuctureVersion = DNS_RPC_ZONE_SECONDARIES_VER;
  245. dwtypeOut = DNSSRV_TYPEID_ZONE_SECONDARIES;
  246. break;
  247. case DNSSRV_TYPEID_ZONE_DATABASE_W2K:
  248. //
  249. // Structures are identical except for dwRpcStuctureVersion.
  250. //
  251. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_DATABASE_WHISTLER );
  252. RtlCopyMemory(
  253. ( PBYTE ) pdataOut + DNS_WHISTLER_VERSION_SIZE,
  254. pdataIn,
  255. sizeof( DNS_RPC_ZONE_DATABASE_W2K ) );
  256. ( ( PDNS_RPC_ZONE_DATABASE_WHISTLER ) pdataOut )->
  257. dwRpcStuctureVersion = DNS_RPC_ZONE_DATABASE_VER;
  258. dwtypeOut = DNSSRV_TYPEID_ZONE_DATABASE;
  259. break;
  260. case DNSSRV_TYPEID_ZONE_TYPE_RESET_W2K:
  261. //
  262. // Structures are identical except for dwRpcStuctureVersion.
  263. //
  264. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_TYPE_RESET_WHISTLER );
  265. RtlCopyMemory(
  266. ( PBYTE ) pdataOut + DNS_WHISTLER_VERSION_SIZE,
  267. pdataIn,
  268. sizeof( DNS_RPC_ZONE_TYPE_RESET_W2K ) );
  269. ( ( PDNS_RPC_ZONE_TYPE_RESET_WHISTLER ) pdataOut )->
  270. dwRpcStuctureVersion = DNS_RPC_ZONE_TYPE_RESET_VER;
  271. dwtypeOut = DNSSRV_TYPEID_ZONE_TYPE_RESET;
  272. break;
  273. case DNSSRV_TYPEID_ZONE_CREATE_W2K:
  274. //
  275. // Structures are identical except for dwRpcStuctureVersion
  276. // and some usage in Whistler of reserved W2K fields. No
  277. // need to be concerned about the newly used reserved, they
  278. // will be NULL in the W2K structure.
  279. //
  280. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_CREATE_INFO_WHISTLER );
  281. RtlCopyMemory(
  282. ( PBYTE ) pdataOut + DNS_WHISTLER_VERSION_SIZE,
  283. pdataIn,
  284. sizeof( DNS_RPC_ZONE_CREATE_INFO_W2K ) );
  285. ( ( PDNS_RPC_ZONE_CREATE_INFO_WHISTLER ) pdataOut )->
  286. dwRpcStuctureVersion = DNS_RPC_ZONE_CREATE_INFO_VER;
  287. dwtypeOut = DNSSRV_TYPEID_ZONE_CREATE;
  288. break;
  289. case DNSSRV_TYPEID_ZONE_LIST_W2K:
  290. {
  291. DWORD dwzoneCount;
  292. DWORD dwzonePtrCount;
  293. PDNS_RPC_ZONE_LIST_WHISTLER pzonelistWhistler;
  294. PDNS_RPC_ZONE_LIST_W2K pzonelistW2K;
  295. //
  296. // Structures are identical except for dwRpcStuctureVersion.
  297. // Note: there is always at least one pointer, even if the
  298. // zone count is zero.
  299. //
  300. pzonelistW2K = ( PDNS_RPC_ZONE_LIST_W2K ) pdataIn;
  301. dwzoneCount = dwzonePtrCount = pzonelistW2K->dwZoneCount;
  302. if ( dwzonePtrCount > 0 )
  303. {
  304. --dwzonePtrCount; // num ptrs after ZONE_LIST struct
  305. }
  306. ALLOCATE_RPC_BYTES(
  307. pzonelistWhistler,
  308. sizeof( DNS_RPC_ZONE_LIST_WHISTLER ) +
  309. sizeof( PDNS_RPC_ZONE_WHISTLER ) * dwzonePtrCount );
  310. pdataOut = pzonelistWhistler;
  311. RtlCopyMemory(
  312. ( PBYTE ) pzonelistWhistler + DNS_WHISTLER_VERSION_SIZE,
  313. pzonelistW2K,
  314. sizeof( DNS_RPC_ZONE_LIST_W2K ) +
  315. sizeof( PDNS_RPC_ZONE_W2K ) * dwzonePtrCount );
  316. pzonelistWhistler->dwRpcStuctureVersion = DNS_RPC_ZONE_LIST_VER;
  317. dwtypeOut = DNSSRV_TYPEID_ZONE_LIST;
  318. //
  319. // The zone array must also be converted. Count the new zones
  320. // as they are successfully created so that if there's an error
  321. // converting one zone we will still have a coherent structure.
  322. //
  323. pzonelistWhistler->dwZoneCount = 0;
  324. for ( i = 0; status == ERROR_SUCCESS && i < dwzoneCount; ++i )
  325. {
  326. DWORD dwtype = DNSSRV_TYPEID_ZONE_W2K;
  327. status = DnsRpc_ConvertToCurrent(
  328. &dwtype,
  329. &pzonelistWhistler->ZoneArray[ i ] );
  330. if ( status != ERROR_SUCCESS )
  331. {
  332. ASSERT( status == ERROR_SUCCESS );
  333. break;
  334. }
  335. ASSERT( dwtype == DNSSRV_TYPEID_ZONE );
  336. ++pzonelistWhistler->dwZoneCount;
  337. }
  338. break;
  339. }
  340. default:
  341. break; // This struct requires no translation.
  342. }
  343. //
  344. // Cleanup and return.
  345. //
  346. Done:
  347. if ( pdwTypeId )
  348. {
  349. *pdwTypeId = dwtypeOut;
  350. }
  351. if ( ppData )
  352. {
  353. *ppData = pdataOut;
  354. }
  355. NoTranslation:
  356. DNSDBG( STUB, (
  357. "%s: status=%d\n type in=%d out=%d\n pdata in=%p out=%p\n", fn,
  358. status,
  359. dwtypeIn,
  360. dwtypeOut,
  361. pdataIn,
  362. *ppData ));
  363. return status;
  364. } // DnsRpc_ConvertToCurrent
  365. DNS_STATUS
  366. DNS_API_FUNCTION
  367. DnsRpc_ConvertToUnversioned(
  368. IN PDWORD pdwTypeId, IN OUT
  369. IN PVOID * ppData, IN OUT
  370. IN BOOL * pfAllocatedRpcStruct OUT OPTIONAL
  371. )
  372. /*++
  373. Routine Description:
  374. Takes any DNS RPC structure as input and if necessary fabricates
  375. the old-style unversioned revision of that structure from the members
  376. of the input structure. This function is cousin to
  377. DnsRpc_ConvertToCurrent.
  378. If a new structure is allocated, the old one is freed and the pointer
  379. value at ppData is replaced. Allocated points within the old struct
  380. will be freed or copied to the new struct. Basically, the client
  381. does not have to worry about freeing any part of the old struct. When
  382. he's done with the new struct he has to free it and it's members, as
  383. usual.
  384. The main use of this function is to allow a new client to send
  385. a new RPC structure (e.g. a ZONE_CREATE structure) to an old DNS
  386. server transparently. This function will attempt to make intelligent
  387. decisions about what to do if there are large functional differences
  388. in the old and new structures.
  389. Arguments:
  390. pdwTypeId - type ID of object pointed to by ppData, value may be
  391. changed to type ID of new object at ppData
  392. ppData - pointer to object, pointer may be replaced by a pointer to
  393. a newly allocated, completed different structure as required
  394. pfAllocatedRpcStruct - if not NULL, value is set to TRUE if
  395. a new structure is allocated by this function - the should request
  396. this information if it needs to know if it should free the
  397. replaced pData pointer using MIDL_user_free()
  398. Return Value:
  399. ERROR_SUCCESS or error code. If return code is not ERROR_SUCCESS, there
  400. has been some kind of fatal error. Assume data invalid in this case.
  401. --*/
  402. {
  403. DBG_FN( "DnsRpc_ConvertToUnversioned" )
  404. DNS_STATUS status = ERROR_SUCCESS;
  405. BOOL fallocatedRpcStruct = FALSE;
  406. DWORD dwtypeIn = -1;
  407. PVOID pdataIn = NULL;
  408. DWORD dwtypeOut = -1;
  409. PVOID pdataOut = NULL;
  410. DWORD i;
  411. if ( !pdwTypeId || !ppData )
  412. {
  413. ASSERT( pdwTypeId && ppData );
  414. status = ERROR_INVALID_DATA;
  415. goto NoTranslation;
  416. }
  417. //
  418. // Shortcuts: do not translate NULL, any structure that is not
  419. // versioned, or any structure that is already in unversioned
  420. // format.
  421. //
  422. if ( *pdwTypeId <= DNSSRV_TYPEID_ZONE_LIST_W2K || *ppData == NULL )
  423. {
  424. goto NoTranslation;
  425. }
  426. dwtypeOut = dwtypeIn = *pdwTypeId;
  427. pdataOut = pdataIn = *ppData;
  428. fallocatedRpcStruct = TRUE;
  429. //
  430. // Giant switch statement of all types that can be downleveled.
  431. //
  432. switch ( dwtypeIn )
  433. {
  434. case DNSSRV_TYPEID_FORWARDERS:
  435. //
  436. // Structures are identical except for dwRpcStuctureVersion.
  437. //
  438. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_FORWARDERS_W2K );
  439. RtlCopyMemory(
  440. pdataOut,
  441. ( PBYTE ) pdataIn + DNS_WHISTLER_VERSION_SIZE,
  442. sizeof( DNS_RPC_FORWARDERS_W2K ) );
  443. dwtypeOut = DNSSRV_TYPEID_FORWARDERS_W2K;
  444. break;
  445. case DNSSRV_TYPEID_ZONE_CREATE:
  446. //
  447. // Whistler has several additional members.
  448. //
  449. {
  450. PDNS_RPC_ZONE_CREATE_INFO_W2K pzoneOut;
  451. PDNS_RPC_ZONE_CREATE_INFO pzoneIn = pdataIn;
  452. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_CREATE_INFO_W2K );
  453. pzoneOut = pdataOut;
  454. pzoneOut->pszZoneName = pzoneIn->pszZoneName;
  455. pzoneOut->dwZoneType = pzoneIn->dwZoneType;
  456. pzoneOut->fAllowUpdate = pzoneIn->fAllowUpdate;
  457. pzoneOut->fAging = pzoneIn->fAging;
  458. pzoneOut->dwFlags = pzoneIn->dwFlags;
  459. pzoneOut->pszDataFile = pzoneIn->pszDataFile;
  460. pzoneOut->fDsIntegrated = pzoneIn->fDsIntegrated;
  461. pzoneOut->fLoadExisting = pzoneIn->fLoadExisting;
  462. pzoneOut->pszAdmin = pzoneIn->pszAdmin;
  463. pzoneOut->aipMasters = pzoneIn->aipMasters;
  464. pzoneOut->aipSecondaries = pzoneIn->aipSecondaries;
  465. pzoneOut->fSecureSecondaries = pzoneIn->fSecureSecondaries;
  466. pzoneOut->fNotifyLevel = pzoneIn->fNotifyLevel;
  467. dwtypeOut = DNSSRV_TYPEID_ZONE_CREATE_W2K;
  468. break;
  469. }
  470. case DNSSRV_TYPEID_ZONE_TYPE_RESET:
  471. //
  472. // Structures are identical except for dwRpcStuctureVersion.
  473. //
  474. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_TYPE_RESET_W2K );
  475. RtlCopyMemory(
  476. pdataOut,
  477. ( PBYTE ) pdataIn + DNS_WHISTLER_VERSION_SIZE,
  478. sizeof( DNS_RPC_ZONE_TYPE_RESET_W2K ) );
  479. dwtypeOut = DNSSRV_TYPEID_ZONE_TYPE_RESET_W2K;
  480. break;
  481. case DNSSRV_TYPEID_ZONE_SECONDARIES:
  482. //
  483. // Structures are identical except for dwRpcStuctureVersion.
  484. //
  485. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_SECONDARIES_W2K );
  486. RtlCopyMemory(
  487. pdataOut,
  488. ( PBYTE ) pdataIn + DNS_WHISTLER_VERSION_SIZE,
  489. sizeof( DNS_RPC_ZONE_SECONDARIES_W2K ) );
  490. dwtypeOut = DNSSRV_TYPEID_ZONE_SECONDARIES_W2K;
  491. break;
  492. case DNSSRV_TYPEID_ZONE_DATABASE:
  493. //
  494. // Structures are identical except for dwRpcStuctureVersion.
  495. //
  496. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_DATABASE_W2K );
  497. RtlCopyMemory(
  498. pdataOut,
  499. ( PBYTE ) pdataIn + DNS_WHISTLER_VERSION_SIZE,
  500. sizeof( DNS_RPC_ZONE_DATABASE_W2K ) );
  501. dwtypeOut = DNSSRV_TYPEID_ZONE_DATABASE_W2K;
  502. break;
  503. default:
  504. fallocatedRpcStruct = FALSE;
  505. break; // Unknown - do nothing.
  506. }
  507. //
  508. // Cleanup and return.
  509. //
  510. Done:
  511. if ( pdwTypeId )
  512. {
  513. *pdwTypeId = dwtypeOut;
  514. }
  515. if ( ppData )
  516. {
  517. *ppData = pdataOut;
  518. }
  519. NoTranslation:
  520. if ( pfAllocatedRpcStruct )
  521. {
  522. *pfAllocatedRpcStruct = fallocatedRpcStruct;
  523. }
  524. DNSDBG( STUB, (
  525. "%s: status=%d\n type in=%d out=%d\n pdata in=%p out=%p\n", fn,
  526. status,
  527. dwtypeIn,
  528. dwtypeOut,
  529. pdataIn,
  530. *ppData ));
  531. return status;
  532. } // DnsRpc_ConvertToUnversioned
  533. //
  534. // RPC functions
  535. //
  536. DNS_STATUS
  537. DNS_API_FUNCTION
  538. DnssrvOperationEx(
  539. IN DWORD dwClientVersion,
  540. IN DWORD dwSettingFlags,
  541. IN LPCWSTR Server,
  542. IN LPCSTR pszZone,
  543. IN DWORD dwContext,
  544. IN LPCSTR pszOperation,
  545. IN DWORD dwTypeId,
  546. IN PVOID pData
  547. )
  548. {
  549. DNS_STATUS status;
  550. DNSSRV_RPC_UNION rpcData;
  551. BOOL fallocatedRpcStruct = FALSE;
  552. DECLARE_DNS_RPC_RETRY_STATE();
  553. rpcData.Null = pData;
  554. IF_DNSDBG( STUB )
  555. {
  556. DNS_PRINT((
  557. "Enter DnssrvOperationEx()\n"
  558. "\tClient ver = 0x%X\n"
  559. "\tServer = %S\n"
  560. "\tZone = %s\n"
  561. "\tContext = %p\n"
  562. "\tOperation = %s\n"
  563. "\tTypeid = %d\n",
  564. dwClientVersion,
  565. Server,
  566. pszZone,
  567. dwContext,
  568. pszOperation,
  569. dwTypeId ));
  570. IF_DNSDBG( STUB2 )
  571. {
  572. DnsDbg_RpcUnion(
  573. "pData for R_DnssrvOperationEx ",
  574. dwTypeId,
  575. rpcData.Null );
  576. }
  577. }
  578. #if 0
  579. // generate multizone context?
  580. //
  581. // DEVNOTE: get this working
  582. if ( pszZone )
  583. {
  584. dwContext = DnssrvGenerateZoneOperationContext( pszZone, dwContext );
  585. }
  586. #endif
  587. DECLARE_DNS_RPC_RETRY_LABEL()
  588. RpcTryExcept
  589. {
  590. ASSERT_DNS_RPC_RETRY_STATE_VALID();
  591. if ( DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_NEW )
  592. {
  593. status = R_DnssrvOperation2(
  594. dwClientVersion,
  595. dwSettingFlags,
  596. Server,
  597. pszZone,
  598. dwContext,
  599. pszOperation,
  600. dwTypeId,
  601. rpcData );
  602. }
  603. else
  604. {
  605. status = R_DnssrvOperation(
  606. Server,
  607. pszZone,
  608. dwContext,
  609. pszOperation,
  610. dwTypeId,
  611. rpcData );
  612. }
  613. ADVANCE_DNS_RPC_RETRY_STATE( status );
  614. IF_DNSDBG( STUB )
  615. {
  616. DNS_PRINT((
  617. "Leave R_DnssrvOperation(): status %d (%p)\n",
  618. status, status ));
  619. }
  620. }
  621. RpcExcept (1)
  622. {
  623. status = RpcExceptionCode();
  624. IF_DNSDBG( STUB )
  625. {
  626. DNS_PRINT((
  627. "RpcExcept: code = %d (%p)\n",
  628. status, status ));
  629. }
  630. //
  631. // For downlevel server, attempt to construct old-style data.
  632. //
  633. DnsRpc_ConvertToUnversioned( &dwTypeId, &pData, &fallocatedRpcStruct );
  634. rpcData.Null = pData;
  635. ADVANCE_DNS_RPC_RETRY_STATE( status );
  636. }
  637. RpcEndExcept
  638. TEST_DNS_RPC_RETRY();
  639. if ( fallocatedRpcStruct )
  640. {
  641. MIDL_user_free( pData );
  642. }
  643. return( status );
  644. }
  645. DNS_STATUS
  646. DNS_API_FUNCTION
  647. DnssrvQueryEx(
  648. IN DWORD dwClientVersion,
  649. IN DWORD dwSettingFlags,
  650. IN LPCWSTR Server,
  651. IN LPCSTR pszZone,
  652. IN LPCSTR pszQuery,
  653. OUT PDWORD pdwTypeId,
  654. OUT PVOID * ppData
  655. )
  656. {
  657. DNS_STATUS status;
  658. DECLARE_DNS_RPC_RETRY_STATE();
  659. IF_DNSDBG( STUB )
  660. {
  661. DNS_PRINT((
  662. "Enter DnssrvQuery()\n"
  663. "\tClient ver = 0x%X\n"
  664. "\tServer = %S\n"
  665. "\tZone = %s\n"
  666. "\tQuery = %s\n",
  667. dwClientVersion,
  668. Server,
  669. pszZone,
  670. pszQuery ));
  671. DNSDBG( STUB2, (
  672. "\tpdwTypeId = %p\n"
  673. "\tppData = %p\n"
  674. "\t*pdwTypeId = %d\n"
  675. "\t*ppData = %p\n",
  676. pdwTypeId,
  677. ppData,
  678. *pdwTypeId,
  679. *ppData ));
  680. }
  681. if ( !pszQuery || !ppData || !pdwTypeId )
  682. {
  683. DNS_ASSERT( FALSE );
  684. return( ERROR_INVALID_PARAMETER );
  685. }
  686. //
  687. // RPC sees ppData as actually a PTR to a UNION structure, and
  688. // for pointer type returns, would like to copy the data back into the
  689. // memory pointed at by the current value of the pointer.
  690. //
  691. // This is not what we want, we just want to capture a pointer to
  692. // the returned data block. To do this init the pointer value to
  693. // be NULL, so RPC will then allocate memory of all pointer types
  694. // in the UNION.
  695. //
  696. *ppData = NULL;
  697. DECLARE_DNS_RPC_RETRY_LABEL()
  698. RpcTryExcept
  699. {
  700. ASSERT_DNS_RPC_RETRY_STATE_VALID();
  701. if ( DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_NEW )
  702. {
  703. status = R_DnssrvQuery2(
  704. dwClientVersion,
  705. dwSettingFlags,
  706. Server,
  707. pszZone,
  708. pszQuery,
  709. pdwTypeId,
  710. ( DNSSRV_RPC_UNION * ) ppData );
  711. }
  712. else
  713. {
  714. status = R_DnssrvQuery(
  715. Server,
  716. pszZone,
  717. pszQuery,
  718. pdwTypeId,
  719. ( DNSSRV_RPC_UNION * ) ppData );
  720. }
  721. ADVANCE_DNS_RPC_RETRY_STATE( status );
  722. IF_DNSDBG( STUB )
  723. {
  724. DNS_PRINT((
  725. "Leave R_DnssrvQuery(): status %d (%p)\n"
  726. "\tTypeId = %d\n"
  727. "\tDataPtr = %p\n",
  728. status, status,
  729. *pdwTypeId,
  730. *ppData ));
  731. if ( ppData )
  732. {
  733. DnsDbg_RpcUnion(
  734. "After R_DnssrvQuery ...\n",
  735. *pdwTypeId,
  736. *ppData );
  737. }
  738. }
  739. }
  740. RpcExcept (1)
  741. {
  742. status = RpcExceptionCode();
  743. IF_DNSDBG( STUB )
  744. {
  745. DNS_PRINT((
  746. "RpcExcept: code = %d (%p)\n",
  747. status, status ));
  748. }
  749. ADVANCE_DNS_RPC_RETRY_STATE( status );
  750. }
  751. RpcEndExcept
  752. TEST_DNS_RPC_RETRY();
  753. //
  754. // Upgrade old structure to new.
  755. //
  756. if ( status == ERROR_SUCCESS )
  757. {
  758. status = DnsRpc_ConvertToCurrent( pdwTypeId, ppData );
  759. }
  760. return( status );
  761. }
  762. DNS_STATUS
  763. DNS_API_FUNCTION
  764. DnssrvComplexOperationEx(
  765. IN DWORD dwClientVersion,
  766. IN DWORD dwSettingFlags,
  767. IN LPCWSTR Server,
  768. IN LPCSTR pszZone,
  769. IN LPCSTR pszOperation,
  770. IN DWORD dwTypeIn,
  771. IN PVOID pDataIn,
  772. OUT PDWORD pdwTypeOut,
  773. OUT PVOID * ppDataOut
  774. )
  775. {
  776. DNS_STATUS status;
  777. DNSSRV_RPC_UNION rpcData;
  778. DECLARE_DNS_RPC_RETRY_STATE();
  779. rpcData.Null = pDataIn;
  780. IF_DNSDBG( STUB )
  781. {
  782. DNS_PRINT((
  783. "Enter DnssrvComplexOperation()\n"
  784. "\tClient ver = 0x%X\n"
  785. "\tServer = %S\n"
  786. "\tZone = %s\n"
  787. "\tOperation = %s\n"
  788. "\tTypeIn = %d\n",
  789. dwClientVersion,
  790. Server,
  791. pszZone,
  792. pszOperation,
  793. dwTypeIn ));
  794. IF_DNSDBG( STUB2 )
  795. {
  796. DnsDbg_RpcUnion(
  797. "pData for R_DnssrvOperation ",
  798. dwTypeIn,
  799. rpcData.Null );
  800. DNS_PRINT((
  801. "\tpdwTypeOut = %p\n"
  802. "\tppDataOut = %p\n"
  803. "\t*pdwTypeOut = %d\n"
  804. "\t*ppDataOut = %p\n",
  805. pdwTypeOut,
  806. ppDataOut,
  807. *pdwTypeOut,
  808. *ppDataOut ));
  809. }
  810. }
  811. if ( !pszOperation || !ppDataOut || !pdwTypeOut )
  812. {
  813. DNS_ASSERT( FALSE );
  814. return( ERROR_INVALID_PARAMETER );
  815. }
  816. //
  817. // RPC sees ppDataOut as actually a PTR to a UNION structure, and
  818. // for pointer type returns, would like to copy the data back into
  819. // the memory pointed at by the current value of the pointer.
  820. //
  821. // This is not what we want, we just want to capture a pointer to
  822. // the returned data block. To do this init the pointer value to
  823. // be NULL, so RPC will then allocate memory of all pointer types
  824. // in the UNION.
  825. //
  826. *ppDataOut = NULL;
  827. DECLARE_DNS_RPC_RETRY_LABEL()
  828. RpcTryExcept
  829. {
  830. ASSERT_DNS_RPC_RETRY_STATE_VALID();
  831. if ( DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_NEW )
  832. {
  833. status = R_DnssrvComplexOperation2(
  834. dwClientVersion,
  835. dwSettingFlags,
  836. Server,
  837. pszZone,
  838. pszOperation,
  839. dwTypeIn,
  840. rpcData,
  841. pdwTypeOut,
  842. ( DNSSRV_RPC_UNION * ) ppDataOut );
  843. }
  844. else
  845. {
  846. status = R_DnssrvComplexOperation(
  847. Server,
  848. pszZone,
  849. pszOperation,
  850. dwTypeIn,
  851. rpcData,
  852. pdwTypeOut,
  853. ( DNSSRV_RPC_UNION * ) ppDataOut );
  854. }
  855. ADVANCE_DNS_RPC_RETRY_STATE( status );
  856. IF_DNSDBG( STUB )
  857. {
  858. DNS_PRINT((
  859. "Leave R_DnssrvComplexOperation(): status %d (%p)\n"
  860. "\tTypeId = %d\n"
  861. "\tDataPtr = %p\n",
  862. status, status,
  863. *pdwTypeOut,
  864. *ppDataOut ));
  865. if ( ppDataOut )
  866. {
  867. DnsDbg_RpcUnion(
  868. "After R_DnssrvQuery ...\n",
  869. *pdwTypeOut,
  870. *ppDataOut );
  871. }
  872. }
  873. }
  874. RpcExcept (1)
  875. {
  876. status = RpcExceptionCode();
  877. IF_DNSDBG( STUB )
  878. {
  879. DNS_PRINT((
  880. "RpcExcept: code = %d (%p)\n",
  881. status, status ));
  882. }
  883. ADVANCE_DNS_RPC_RETRY_STATE( status );
  884. }
  885. RpcEndExcept
  886. TEST_DNS_RPC_RETRY();
  887. //
  888. // Upgrade old structure to new.
  889. //
  890. if ( status == ERROR_SUCCESS )
  891. {
  892. status = DnsRpc_ConvertToCurrent( pdwTypeOut, ppDataOut );
  893. }
  894. return( status );
  895. }
  896. DNS_STATUS
  897. DNS_API_FUNCTION
  898. DnssrvEnumRecordsEx(
  899. IN DWORD dwClientVersion,
  900. IN DWORD dwSettingFlags,
  901. IN LPCWSTR Server,
  902. IN LPCSTR pszZoneName,
  903. IN LPCSTR pszNodeName,
  904. IN LPCSTR pszStartChild,
  905. IN WORD wRecordType,
  906. IN DWORD dwSelectFlag,
  907. IN LPCSTR pszFilterStart,
  908. IN LPCSTR pszFilterStop,
  909. IN OUT PDWORD pdwBufferLength,
  910. OUT PBYTE * ppBuffer
  911. )
  912. /*++
  913. Routine Description:
  914. Stub for EnumRecords API.
  915. Note, this matches DnssrvEnumRecords() API exactly.
  916. The "Stub" suffix is attached to distinguish from the actual
  917. DnssrvEnumRecords() (remote.c) which handles NT4 server compatibility.
  918. When that is no longer desired, that routine may be eliminated and
  919. this the "Stub" suffix removed from this routine.
  920. Arguments:
  921. Return Value:
  922. ERROR_SUCCESS on successful enumeration.
  923. ERROR_MORE_DATA when buffer full and more data remains.
  924. ErrorCode on failure.
  925. --*/
  926. {
  927. DNS_STATUS status;
  928. DECLARE_DNS_RPC_RETRY_STATE();
  929. DNSDBG( STUB, (
  930. "Enter DnssrvEnumRecords()\n"
  931. "\tClient ver = 0x%X\n"
  932. "\tServer = %S\n"
  933. "\tpszZoneName = %s\n"
  934. "\tpszNodeName = %s\n"
  935. "\tpszStartChild = %s\n"
  936. "\twRecordType = %d\n"
  937. "\tdwSelectFlag = %p\n"
  938. "\tpszFilterStart = %s\n"
  939. "\tpszFilterStop = %s\n"
  940. "\tpdwBufferLength = %p\n"
  941. "\tppBuffer = %p\n",
  942. dwClientVersion,
  943. Server,
  944. pszZoneName,
  945. pszNodeName,
  946. pszStartChild,
  947. wRecordType,
  948. dwSelectFlag,
  949. pszFilterStart,
  950. pszFilterStop,
  951. pdwBufferLength,
  952. ppBuffer ));
  953. DECLARE_DNS_RPC_RETRY_LABEL()
  954. RpcTryExcept
  955. {
  956. // clear ptr for safety, we don't want to free any bogus memory
  957. *ppBuffer = NULL;
  958. ASSERT_DNS_RPC_RETRY_STATE_VALID();
  959. if ( DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_NEW )
  960. {
  961. status = R_DnssrvEnumRecords2(
  962. dwClientVersion,
  963. dwSettingFlags,
  964. Server,
  965. pszZoneName,
  966. pszNodeName,
  967. pszStartChild,
  968. wRecordType,
  969. dwSelectFlag,
  970. pszFilterStart,
  971. pszFilterStop,
  972. pdwBufferLength,
  973. ppBuffer );
  974. }
  975. else
  976. {
  977. status = R_DnssrvEnumRecords(
  978. Server,
  979. pszZoneName,
  980. pszNodeName,
  981. pszStartChild,
  982. wRecordType,
  983. dwSelectFlag,
  984. pszFilterStart,
  985. pszFilterStop,
  986. pdwBufferLength,
  987. ppBuffer );
  988. }
  989. ADVANCE_DNS_RPC_RETRY_STATE( status );
  990. IF_DNSDBG( STUB )
  991. {
  992. DNS_PRINT((
  993. "R_DnssrvEnumRecords: try = %d status = %d / %p\n",
  994. DNS_RPC_RETRY_STATE(),
  995. status,
  996. status ));
  997. if ( status == ERROR_SUCCESS || status == ERROR_MORE_DATA )
  998. {
  999. DnsDbg_RpcRecordsInBuffer(
  1000. "Returned records: ",
  1001. *pdwBufferLength,
  1002. *ppBuffer );
  1003. }
  1004. }
  1005. }
  1006. RpcExcept (1)
  1007. {
  1008. status = RpcExceptionCode();
  1009. IF_DNSDBG( STUB )
  1010. {
  1011. DNS_PRINT((
  1012. "RpcExcept: code = %d / %p\n",
  1013. status,
  1014. status ));
  1015. }
  1016. ADVANCE_DNS_RPC_RETRY_STATE( status );
  1017. }
  1018. RpcEndExcept
  1019. TEST_DNS_RPC_RETRY();
  1020. return status;
  1021. }
  1022. DNS_STATUS
  1023. DNS_API_FUNCTION
  1024. DnssrvUpdateRecordEx(
  1025. IN DWORD dwClientVersion,
  1026. IN DWORD dwSettingFlags,
  1027. IN LPCWSTR Server,
  1028. IN LPCSTR pszZoneName,
  1029. IN LPCSTR pszNodeName,
  1030. IN PDNS_RPC_RECORD pAddRecord,
  1031. IN PDNS_RPC_RECORD pDeleteRecord
  1032. )
  1033. /*++
  1034. Routine Description:
  1035. Stub for UpdateRecords API.
  1036. Arguments:
  1037. Return Value:
  1038. ERROR_SUCCESS on successful enumeration.
  1039. ErrorCode on failure.
  1040. --*/
  1041. {
  1042. DNS_STATUS status;
  1043. DECLARE_DNS_RPC_RETRY_STATE();
  1044. DNSDBG( STUB, (
  1045. "Enter R_DnssrvUpdateRecord()\n"
  1046. "\tClient ver = 0x%X\n"
  1047. "\tServer = %S\n"
  1048. "\tpszZoneName = %s\n"
  1049. "\tpszNodeName = %s\n"
  1050. "\tpAddRecord = %p\n"
  1051. "\tpDeleteRecord = %p\n",
  1052. dwClientVersion,
  1053. Server,
  1054. pszZoneName,
  1055. pszNodeName,
  1056. pAddRecord,
  1057. pDeleteRecord ));
  1058. DECLARE_DNS_RPC_RETRY_LABEL()
  1059. RpcTryExcept
  1060. {
  1061. ASSERT_DNS_RPC_RETRY_STATE_VALID();
  1062. if ( DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_NEW )
  1063. {
  1064. status = R_DnssrvUpdateRecord2(
  1065. dwClientVersion,
  1066. dwSettingFlags,
  1067. Server,
  1068. pszZoneName,
  1069. pszNodeName,
  1070. pAddRecord,
  1071. pDeleteRecord );
  1072. }
  1073. else
  1074. {
  1075. status = R_DnssrvUpdateRecord(
  1076. Server,
  1077. pszZoneName,
  1078. pszNodeName,
  1079. pAddRecord,
  1080. pDeleteRecord );
  1081. }
  1082. ADVANCE_DNS_RPC_RETRY_STATE( status );
  1083. DNSDBG( STUB, (
  1084. "R_DnssrvUpdateRecord: status = %d / %p\n",
  1085. status, status ));
  1086. }
  1087. RpcExcept (1)
  1088. {
  1089. status = RpcExceptionCode();
  1090. DNSDBG( STUB, (
  1091. "RpcExcept: code = %d / %p\n",
  1092. status, status ));
  1093. ADVANCE_DNS_RPC_RETRY_STATE( status );
  1094. }
  1095. RpcEndExcept
  1096. TEST_DNS_RPC_RETRY();
  1097. return( status );
  1098. }
  1099. //
  1100. // End stub.c
  1101. //