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.

1718 lines
51 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. #include "rpcasync.h"
  18. #endif
  19. //
  20. // For versioning, we use a simple state machine in each function's
  21. // RPC exception block to try the new RPC call then the old RPC call.
  22. // If there is any RPC error, retry a downlevel operation.
  23. //
  24. // This macro'ing is a bit overkill, but each RPC interface wrapper
  25. // needs this retry logic.
  26. //
  27. #define DNS_RPC_RETRY_STATE() iDnsRpcRetryState
  28. #define DECLARE_DNS_RPC_RETRY_LABEL() DnsRpcRetryLabel:
  29. #define DECLARE_DNS_RPC_RETRY_STATE( status ) \
  30. INT DNS_RPC_RETRY_STATE() = 0; \
  31. status = dnsrpcInitializeTls()
  32. // Test return code to see if we need to retry for W2K remote RPC server.
  33. #define ADVANCE_DNS_RPC_RETRY_STATE( dwStatus ) \
  34. if ( DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_NEW && \
  35. dwStatus != RPC_S_SEC_PKG_ERROR && \
  36. ( dwStatus == ERROR_SUCCESS || \
  37. dwStatus == RPC_S_SERVER_UNAVAILABLE || \
  38. dwStatus < RPC_S_INVALID_STRING_BINDING || \
  39. dwStatus > RPC_X_BAD_STUB_DATA ) ) \
  40. DNS_RPC_RETRY_STATE() = DNS_RPC_TRY_DONE; \
  41. else \
  42. { \
  43. dnsrpcSetW2KBindFlag( TRUE ); \
  44. ++DNS_RPC_RETRY_STATE(); \
  45. }
  46. #define TEST_DNS_RPC_RETRY() \
  47. if ( DNS_RPC_RETRY_STATE() < DNS_RPC_TRY_DONE ) { goto DnsRpcRetryLabel; }
  48. #define ASSERT_DNS_RPC_RETRY_STATE_VALID() \
  49. ASSERT( DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_NEW || \
  50. DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_OLD )
  51. #define DNS_RPC_TRY_NEW 0
  52. #define DNS_RPC_TRY_OLD 1
  53. #define DNS_RPC_TRY_DONE 2
  54. //
  55. // This macro is a safety helper for use in DnsRpc_ConvertToCurrent.
  56. //
  57. // If header definitions change, DnsRpc_ConvertToCurrent can
  58. // start doing wacky things. Using memcpy instead of individual
  59. // assignments saves instructions but is potentially dangerous if
  60. // headers change and this function is not updated. Add ASSERTS
  61. // where possible to try and catch header changes that have not
  62. // been accounted for here. A general principal is that a structure
  63. // may grow but not shrink in size between versions.
  64. //
  65. #if DBG
  66. #define DNS_ASSERT_CURRENT_LARGER( structName ) \
  67. ASSERT( sizeof( DNS_RPC_##structName##_DOTNET ) >= \
  68. sizeof( DNS_RPC_##structName##_W2K ) );
  69. #define DNS_ASSERT_RPC_STRUCTS_ARE_SANE() \
  70. { \
  71. static LONG finit = 0; \
  72. \
  73. if ( InterlockedIncrement( &finit ) != 1 ) \
  74. { \
  75. goto DoneDbgAsserts; \
  76. } \
  77. \
  78. DNS_ASSERT_CURRENT_LARGER( SERVER_INFO ); \
  79. DNS_ASSERT_CURRENT_LARGER( FORWARDERS ); \
  80. DNS_ASSERT_CURRENT_LARGER( ZONE ); \
  81. DNS_ASSERT_CURRENT_LARGER( ZONE_INFO ); \
  82. DNS_ASSERT_CURRENT_LARGER( ZONE_SECONDARIES ); \
  83. DNS_ASSERT_CURRENT_LARGER( ZONE_DATABASE ); \
  84. DNS_ASSERT_CURRENT_LARGER( ZONE_TYPE_RESET ); \
  85. DNS_ASSERT_CURRENT_LARGER( ZONE_CREATE_INFO ); \
  86. DNS_ASSERT_CURRENT_LARGER( ZONE_LIST ); \
  87. DNS_ASSERT_CURRENT_LARGER( SERVER_INFO ); \
  88. DNS_ASSERT_CURRENT_LARGER( FORWARDERS ); \
  89. DNS_ASSERT_CURRENT_LARGER( ZONE ); \
  90. DNS_ASSERT_CURRENT_LARGER( ZONE_SECONDARIES ); \
  91. DNS_ASSERT_CURRENT_LARGER( ZONE_DATABASE ); \
  92. DNS_ASSERT_CURRENT_LARGER( ZONE_TYPE_RESET ); \
  93. DNS_ASSERT_CURRENT_LARGER( ZONE_LIST ); \
  94. \
  95. DoneDbgAsserts: ; \
  96. }
  97. #else
  98. #define DNS_ASSERT_RPC_STRUCTS_ARE_SANE()
  99. #endif // DBG
  100. DWORD g_bAttemptW2KRPCBindTlsIndex = TLS_OUT_OF_INDEXES;
  101. DNS_STATUS
  102. dnsrpcInitializeTls(
  103. VOID
  104. )
  105. /*++
  106. Routine Description:
  107. The W2K RPC bind global retry flag is stored in thread local
  108. storage. Each stub function must make certain that the TLS index
  109. is allocated before calling any RPC interface. Unfortunately there
  110. is no initialization function called by clients of DNSRPC.LIB
  111. where this can be done.
  112. NOTE: the TLS block is never freed. There is no convenient place
  113. to clean it up so for now just let it persist until process
  114. termination. This is harmless and is not a leak.
  115. Arguments:
  116. Return Value:
  117. On failure, there was a TLS error - likely too many TLS indices
  118. have been allocated in this process.
  119. --*/
  120. {
  121. static LONG dnsrpcTlsInitialized = 0;
  122. DWORD tlsIndex;
  123. DNS_STATUS status = ERROR_SUCCESS;
  124. //
  125. // Quick-check: already initialized?
  126. //
  127. if ( dnsrpcTlsInitialized )
  128. {
  129. goto Done;
  130. }
  131. //
  132. // Safe-check for initialization. If two threads attempt to initialize
  133. // at the same time the quick-check above may pass both. The safe check
  134. // will ensure that only one thread will actually perform initialization.
  135. //
  136. if ( InterlockedIncrement( &dnsrpcTlsInitialized ) != 1 )
  137. {
  138. InterlockedDecrement( &dnsrpcTlsInitialized );
  139. goto Done;
  140. }
  141. //
  142. // Initialize the TLS index for the DNSRPC W2K retry flag.
  143. //
  144. tlsIndex = TlsAlloc();
  145. ASSERT( tlsIndex != TLS_OUT_OF_INDEXES );
  146. if ( tlsIndex == TLS_OUT_OF_INDEXES )
  147. {
  148. status = GetLastError();
  149. goto Done;
  150. }
  151. g_bAttemptW2KRPCBindTlsIndex = tlsIndex;
  152. //
  153. // Provide initial flag value.
  154. //
  155. dnsrpcSetW2KBindFlag( FALSE );
  156. Done:
  157. return status;
  158. } // dnsrpcInitializeTls
  159. VOID
  160. dnsrpcSetW2KBindFlag(
  161. BOOL newFlagValue
  162. )
  163. /*++
  164. Routine Description:
  165. Sets the W2K bind retry flag in thread local storage.
  166. Arguments:
  167. newFlagValue -- new flag value to be stored in TLS
  168. Return Value:
  169. --*/
  170. {
  171. DWORD tlsIndex = g_bAttemptW2KRPCBindTlsIndex;
  172. ASSERT( tlsIndex != TLS_OUT_OF_INDEXES );
  173. if ( tlsIndex != TLS_OUT_OF_INDEXES )
  174. {
  175. TlsSetValue( tlsIndex, ( LPVOID ) ( DWORD_PTR ) newFlagValue );
  176. }
  177. } // dnsrpcSetW2KBindFlag
  178. BOOL
  179. dnsrpcGetW2KBindFlag(
  180. VOID
  181. )
  182. /*++
  183. Routine Description:
  184. Gets the W2K bind retry flag from thread local storage.
  185. Arguments:
  186. Return Value:
  187. The current value of this thread's W2K bind retry flag.
  188. --*/
  189. {
  190. DWORD tlsIndex = g_bAttemptW2KRPCBindTlsIndex;
  191. ASSERT( tlsIndex != TLS_OUT_OF_INDEXES );
  192. if ( tlsIndex == TLS_OUT_OF_INDEXES )
  193. {
  194. return FALSE;
  195. }
  196. else
  197. {
  198. return ( BOOL ) ( DWORD_PTR ) TlsGetValue( tlsIndex );
  199. }
  200. } // dnsrpcSetW2KBindFlag
  201. VOID
  202. printExtendedRpcErrorInfo(
  203. DNS_STATUS externalStatus
  204. )
  205. /*++
  206. Routine Description:
  207. Prints extended RPC error information to console.
  208. Arguments:
  209. Return Value:
  210. --*/
  211. {
  212. #if DBG
  213. DBG_FN( "RpcError" )
  214. RPC_STATUS status;
  215. RPC_ERROR_ENUM_HANDLE enumHandle;
  216. if ( externalStatus == ERROR_SUCCESS )
  217. {
  218. return;
  219. }
  220. status = RpcErrorStartEnumeration( &enumHandle );
  221. if ( status != RPC_S_OK )
  222. {
  223. printf( "%s: error %d retrieving RPC error information\n", fn, status );
  224. }
  225. else
  226. {
  227. RPC_EXTENDED_ERROR_INFO errorInfo;
  228. int records;
  229. BOOL result;
  230. BOOL copyStrings = TRUE;
  231. BOOL fuseFileTime = TRUE;
  232. SYSTEMTIME * systemTimeToUse;
  233. SYSTEMTIME systemTimeBuffer;
  234. while ( status == RPC_S_OK )
  235. {
  236. errorInfo.Version = RPC_EEINFO_VERSION;
  237. errorInfo.Flags = 0;
  238. errorInfo.NumberOfParameters = 4;
  239. if ( fuseFileTime )
  240. {
  241. errorInfo.Flags |= EEInfoUseFileTime;
  242. }
  243. status = RpcErrorGetNextRecord( &enumHandle, copyStrings, &errorInfo );
  244. if ( status == RPC_S_ENTRY_NOT_FOUND )
  245. {
  246. break;
  247. }
  248. else if ( status != RPC_S_OK )
  249. {
  250. printf( "%s: error %d during error info enumeration\n", fn, status );
  251. break;
  252. }
  253. else
  254. {
  255. int i;
  256. if ( errorInfo.ComputerName )
  257. {
  258. printf( "%s: ComputerName %S\n", fn, errorInfo.ComputerName );
  259. if ( copyStrings )
  260. {
  261. result = HeapFree( GetProcessHeap(), 0, errorInfo.ComputerName );
  262. ASSERT( result );
  263. }
  264. }
  265. printf( "ProcessID is %d\n", errorInfo.ProcessID );
  266. if ( fuseFileTime )
  267. {
  268. result = FileTimeToSystemTime(
  269. &errorInfo.u.FileTime,
  270. &systemTimeBuffer);
  271. ASSERT( result );
  272. systemTimeToUse = &systemTimeBuffer;
  273. }
  274. else
  275. {
  276. systemTimeToUse = &errorInfo.u.SystemTime;
  277. }
  278. printf(
  279. "System Time is: %d/%d/%d %d:%d:%d:%d\n",
  280. systemTimeToUse->wMonth,
  281. systemTimeToUse->wDay,
  282. systemTimeToUse->wYear,
  283. systemTimeToUse->wHour,
  284. systemTimeToUse->wMinute,
  285. systemTimeToUse->wSecond,
  286. systemTimeToUse->wMilliseconds );
  287. printf( "Generating component is %d\n", errorInfo.GeneratingComponent );
  288. printf( "Status is %d\n", errorInfo.Status );
  289. printf( "Detection location is %d\n", ( int ) errorInfo.DetectionLocation );
  290. printf( "Flags is %d\n", errorInfo.Flags );
  291. printf( "NumberOfParameters is %d\n", errorInfo.NumberOfParameters );
  292. for ( i = 0; i < errorInfo.NumberOfParameters; ++i )
  293. {
  294. switch( errorInfo.Parameters[i].ParameterType )
  295. {
  296. case eeptAnsiString:
  297. printf( "Ansi string: %s\n",
  298. errorInfo.Parameters[i].u.AnsiString );
  299. if ( copyStrings )
  300. {
  301. result = HeapFree( GetProcessHeap(),
  302. 0,
  303. errorInfo.Parameters[i].u.AnsiString );
  304. ASSERT( result );
  305. }
  306. break;
  307. case eeptUnicodeString:
  308. printf( "Unicode string: %S\n",
  309. errorInfo.Parameters[i].u.UnicodeString );
  310. if ( copyStrings )
  311. {
  312. result = HeapFree(
  313. GetProcessHeap(),
  314. 0,
  315. errorInfo.Parameters[i].u.UnicodeString );
  316. ASSERT( result );
  317. }
  318. break;
  319. case eeptLongVal:
  320. printf( "Long val: %d\n", errorInfo.Parameters[i].u.LVal );
  321. break;
  322. case eeptShortVal:
  323. printf( "Short val: %d\n", ( int ) errorInfo.Parameters[i].u.SVal );
  324. break;
  325. case eeptPointerVal:
  326. printf( "Pointer val: %d\n", errorInfo.Parameters[i].u.PVal );
  327. break;
  328. case eeptNone:
  329. printf( "Truncated\n" );
  330. break;
  331. default:
  332. printf( "Invalid type: %d\n", errorInfo.Parameters[i].ParameterType );
  333. break;
  334. }
  335. }
  336. }
  337. }
  338. RpcErrorEndEnumeration( &enumHandle );
  339. }
  340. #endif
  341. } // printExtendedRpcErrorInfo
  342. DNS_STATUS
  343. DNS_API_FUNCTION
  344. DnsRpc_ConvertToCurrent(
  345. IN PDWORD pdwTypeId, IN OUT
  346. IN PVOID * ppData IN OUT
  347. )
  348. /*++
  349. Routine Description:
  350. Takes any DNS RPC structure as input and if necessary fabricates
  351. the latest revision of that structure from the members of the input
  352. structure.
  353. If a new structure is allocated, the old one is freed and the pointer
  354. value at ppData is replaced. Allocated points within the old struct
  355. will be freed or copied to the new struct. Basically, the client
  356. does not have to worry about freeing any part of the old struct. When
  357. he's done with the new struct he has to free it and it's members, as
  358. usual.
  359. There are two main uses of this function:
  360. - If an old client sends the DNS server an input structure, such as
  361. ZONE_CREATE, the new DNS server can use this function to update
  362. the structure so that it can be processed.
  363. - If an old server sends the DNS RPC client an output structure, such
  364. as SERVER_INFO, the new DNS RPC client can use this function to
  365. update the structure so that it can be processed.
  366. Arguments:
  367. pdwTypeId - type ID of object pointed to by ppData, value may be
  368. changed to type ID of new object at ppData
  369. ppData - pointer to object, pointer may be replaced by a pointer to
  370. a newly allocated, completed different structure as required
  371. Return Value:
  372. ERROR_SUCCESS or error code. If return code is not ERROR_SUCCESS, there
  373. has been some kind of fatal error. Assume data invalid in this case.
  374. --*/
  375. {
  376. DBG_FN( "DnsRpc_ConvertToCurrent" )
  377. DNS_STATUS status = ERROR_SUCCESS;
  378. DWORD dwtypeIn = -1;
  379. PVOID pdataIn = NULL;
  380. DWORD dwtypeOut = -1;
  381. PVOID pdataOut = NULL;
  382. DWORD i;
  383. if ( !pdwTypeId || !ppData )
  384. {
  385. ASSERT( pdwTypeId && ppData );
  386. status = ERROR_INVALID_DATA;
  387. goto NoTranslation;
  388. }
  389. //
  390. // Shortcuts: do not translate NULL or certain common types.
  391. //
  392. if ( *pdwTypeId < DNSSRV_TYPEID_SERVER_INFO_W2K || *ppData == NULL )
  393. {
  394. goto NoTranslation;
  395. }
  396. dwtypeOut = dwtypeIn = *pdwTypeId;
  397. pdataOut = pdataIn = *ppData;
  398. DNS_ASSERT_RPC_STRUCTS_ARE_SANE();
  399. //
  400. // Handy macros to make allocating the differently sized structs easy.
  401. //
  402. #define ALLOCATE_RPC_BYTES( ptr, byteCount ) \
  403. ptr = MIDL_user_allocate( byteCount ); \
  404. if ( ptr == NULL ) \
  405. { \
  406. status = DNS_ERROR_NO_MEMORY; \
  407. goto Done; \
  408. } \
  409. RtlZeroMemory( ptr, byteCount );
  410. #define ALLOCATE_RPC_STRUCT( ptr, structType ) \
  411. ALLOCATE_RPC_BYTES( ptr, sizeof( structType ) );
  412. #define DNS_DOTNET_VERSION_SIZE ( 2 * sizeof( DWORD ) )
  413. //
  414. // Giant switch statement of all types that are no longer current.
  415. //
  416. // Add to this switch as we create more versions of types. The idea
  417. // is to convert any structure from an old server to the
  418. // corresponding current version so that the RPC client doesn't
  419. // have to worry about multiple versions of the structures.
  420. //
  421. switch ( dwtypeIn )
  422. {
  423. case DNSSRV_TYPEID_SERVER_INFO_W2K:
  424. //
  425. // Do a member-by-member copy so .NET is not contrained
  426. // by the W2K structure layout.
  427. //
  428. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_SERVER_INFO_DOTNET );
  429. #define MEMBERCOPY( _Member ) \
  430. ( ( PDNS_RPC_SERVER_INFO_DOTNET ) pdataOut )->_Member = \
  431. ( ( PDNS_RPC_SERVER_INFO_W2K ) pdataIn )->_Member
  432. MEMBERCOPY( dwVersion );
  433. MEMBERCOPY( fAdminConfigured );
  434. MEMBERCOPY( fAllowUpdate );
  435. MEMBERCOPY( fDsAvailable );
  436. MEMBERCOPY( pszServerName );
  437. MEMBERCOPY( pszDsContainer );
  438. MEMBERCOPY( aipServerAddrs );
  439. MEMBERCOPY( aipListenAddrs );
  440. MEMBERCOPY( aipForwarders );
  441. MEMBERCOPY( dwLogLevel );
  442. MEMBERCOPY( dwDebugLevel );
  443. MEMBERCOPY( dwForwardTimeout );
  444. MEMBERCOPY( dwRpcProtocol );
  445. MEMBERCOPY( dwNameCheckFlag );
  446. MEMBERCOPY( cAddressAnswerLimit );
  447. MEMBERCOPY( dwRecursionTimeout );
  448. MEMBERCOPY( dwMaxCacheTtl );
  449. MEMBERCOPY( dwDsPollingInterval );
  450. MEMBERCOPY( dwScavengingInterval );
  451. MEMBERCOPY( dwDefaultRefreshInterval );
  452. MEMBERCOPY( dwDefaultNoRefreshInterval );
  453. MEMBERCOPY( fAutoReverseZones );
  454. MEMBERCOPY( fAutoCacheUpdate );
  455. MEMBERCOPY( fSlave );
  456. MEMBERCOPY( fForwardDelegations );
  457. MEMBERCOPY( fNoRecursion );
  458. MEMBERCOPY( fSecureResponses );
  459. MEMBERCOPY( fRoundRobin );
  460. MEMBERCOPY( fLocalNetPriority );
  461. MEMBERCOPY( fBindSecondaries );
  462. MEMBERCOPY( fWriteAuthorityNs );
  463. MEMBERCOPY( fStrictFileParsing );
  464. MEMBERCOPY( fLooseWildcarding );
  465. MEMBERCOPY( fDefaultAgingState );
  466. MEMBERCOPY( dwMaxCacheTtl );
  467. MEMBERCOPY( dwMaxCacheTtl );
  468. dwtypeOut = DNSSRV_TYPEID_SERVER_INFO;
  469. break;
  470. case DNSSRV_TYPEID_FORWARDERS_W2K:
  471. //
  472. // Structures are identical except for dwRpcStructureVersion.
  473. //
  474. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_FORWARDERS_DOTNET );
  475. RtlCopyMemory(
  476. ( PBYTE ) pdataOut + DNS_DOTNET_VERSION_SIZE,
  477. pdataIn,
  478. sizeof( DNS_RPC_FORWARDERS_W2K ) );
  479. ( ( PDNS_RPC_FORWARDERS_DOTNET ) pdataOut )->
  480. dwRpcStructureVersion = DNS_RPC_FORWARDERS_VER;
  481. dwtypeOut = DNSSRV_TYPEID_FORWARDERS;
  482. break;
  483. case DNSSRV_TYPEID_ZONE_W2K:
  484. //
  485. // Structures are identical except for dwRpcStructureVersion.
  486. //
  487. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_DOTNET );
  488. RtlCopyMemory(
  489. ( PBYTE ) pdataOut + DNS_DOTNET_VERSION_SIZE,
  490. pdataIn,
  491. sizeof( DNS_RPC_ZONE_W2K ) );
  492. ( ( PDNS_RPC_ZONE_DOTNET ) pdataOut )->
  493. dwRpcStructureVersion = DNS_RPC_ZONE_VER;
  494. dwtypeOut = DNSSRV_TYPEID_ZONE;
  495. break;
  496. case DNSSRV_TYPEID_ZONE_INFO_W2K:
  497. //
  498. // .NET structure is larger and has new fields for
  499. // forwarder zones, stub zones, directory partitions, etc.
  500. // The structures are identical up to the beginning of
  501. // the reserved DWORDs at the end of the W2K structure.
  502. //
  503. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_INFO_DOTNET );
  504. RtlZeroMemory( pdataOut, sizeof( DNS_RPC_ZONE_INFO_DOTNET ) );
  505. RtlCopyMemory(
  506. ( PBYTE ) pdataOut + DNS_DOTNET_VERSION_SIZE,
  507. pdataIn,
  508. sizeof( DNS_RPC_ZONE_INFO_W2K ) );
  509. ( ( PDNS_RPC_ZONE_INFO_DOTNET ) pdataOut )->
  510. dwRpcStructureVersion = DNS_RPC_ZONE_VER;
  511. dwtypeOut = DNSSRV_TYPEID_ZONE_INFO;
  512. break;
  513. case DNSSRV_TYPEID_ZONE_SECONDARIES_W2K:
  514. //
  515. // Structures are identical except for dwRpcStructureVersion.
  516. //
  517. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_SECONDARIES_DOTNET );
  518. RtlCopyMemory(
  519. ( PBYTE ) pdataOut + DNS_DOTNET_VERSION_SIZE,
  520. pdataIn,
  521. sizeof( DNS_RPC_ZONE_SECONDARIES_W2K ) );
  522. ( ( PDNS_RPC_ZONE_SECONDARIES_DOTNET ) pdataOut )->
  523. dwRpcStructureVersion = DNS_RPC_ZONE_SECONDARIES_VER;
  524. dwtypeOut = DNSSRV_TYPEID_ZONE_SECONDARIES;
  525. break;
  526. case DNSSRV_TYPEID_ZONE_DATABASE_W2K:
  527. //
  528. // Structures are identical except for dwRpcStructureVersion.
  529. //
  530. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_DATABASE_DOTNET );
  531. RtlCopyMemory(
  532. ( PBYTE ) pdataOut + DNS_DOTNET_VERSION_SIZE,
  533. pdataIn,
  534. sizeof( DNS_RPC_ZONE_DATABASE_W2K ) );
  535. ( ( PDNS_RPC_ZONE_DATABASE_DOTNET ) pdataOut )->
  536. dwRpcStructureVersion = DNS_RPC_ZONE_DATABASE_VER;
  537. dwtypeOut = DNSSRV_TYPEID_ZONE_DATABASE;
  538. break;
  539. case DNSSRV_TYPEID_ZONE_TYPE_RESET_W2K:
  540. //
  541. // Structures are identical except for dwRpcStructureVersion.
  542. //
  543. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_TYPE_RESET_DOTNET );
  544. RtlCopyMemory(
  545. ( PBYTE ) pdataOut + DNS_DOTNET_VERSION_SIZE,
  546. pdataIn,
  547. sizeof( DNS_RPC_ZONE_TYPE_RESET_W2K ) );
  548. ( ( PDNS_RPC_ZONE_TYPE_RESET_DOTNET ) pdataOut )->
  549. dwRpcStructureVersion = DNS_RPC_ZONE_TYPE_RESET_VER;
  550. dwtypeOut = DNSSRV_TYPEID_ZONE_TYPE_RESET;
  551. break;
  552. case DNSSRV_TYPEID_ZONE_CREATE_W2K:
  553. //
  554. // Structures are identical except for dwRpcStructureVersion
  555. // and some usage in .NET of reserved W2K fields. No
  556. // need to be concerned about the newly used reserved, they
  557. // will be NULL in the W2K structure.
  558. //
  559. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_CREATE_INFO_DOTNET );
  560. RtlCopyMemory(
  561. ( PBYTE ) pdataOut + DNS_DOTNET_VERSION_SIZE,
  562. pdataIn,
  563. sizeof( DNS_RPC_ZONE_CREATE_INFO_W2K ) );
  564. ( ( PDNS_RPC_ZONE_CREATE_INFO_DOTNET ) pdataOut )->
  565. dwRpcStructureVersion = DNS_RPC_ZONE_CREATE_INFO_VER;
  566. dwtypeOut = DNSSRV_TYPEID_ZONE_CREATE;
  567. break;
  568. case DNSSRV_TYPEID_ZONE_LIST_W2K:
  569. {
  570. DWORD dwzoneCount;
  571. DWORD dwzonePtrCount;
  572. PDNS_RPC_ZONE_LIST_DOTNET pzonelistDotNet;
  573. PDNS_RPC_ZONE_LIST_W2K pzonelistW2K;
  574. //
  575. // Structures are identical except for dwRpcStructureVersion.
  576. // Note: there is always at least one pointer, even if the
  577. // zone count is zero.
  578. //
  579. pzonelistW2K = ( PDNS_RPC_ZONE_LIST_W2K ) pdataIn;
  580. dwzoneCount = dwzonePtrCount = pzonelistW2K->dwZoneCount;
  581. if ( dwzonePtrCount > 0 )
  582. {
  583. --dwzonePtrCount; // num ptrs after ZONE_LIST struct
  584. }
  585. ALLOCATE_RPC_BYTES(
  586. pzonelistDotNet,
  587. sizeof( DNS_RPC_ZONE_LIST_DOTNET ) +
  588. sizeof( PDNS_RPC_ZONE_DOTNET ) * dwzonePtrCount );
  589. pdataOut = pzonelistDotNet;
  590. RtlCopyMemory(
  591. ( PBYTE ) pzonelistDotNet + DNS_DOTNET_VERSION_SIZE,
  592. pzonelistW2K,
  593. sizeof( DNS_RPC_ZONE_LIST_W2K ) +
  594. sizeof( PDNS_RPC_ZONE_W2K ) * dwzonePtrCount );
  595. pzonelistDotNet->dwRpcStructureVersion = DNS_RPC_ZONE_LIST_VER;
  596. dwtypeOut = DNSSRV_TYPEID_ZONE_LIST;
  597. //
  598. // The zone array must also be converted. Count the new zones
  599. // as they are successfully created so that if there's an error
  600. // converting one zone we will still have a coherent structure.
  601. //
  602. pzonelistDotNet->dwZoneCount = 0;
  603. for ( i = 0; status == ERROR_SUCCESS && i < dwzoneCount; ++i )
  604. {
  605. DWORD dwtype = DNSSRV_TYPEID_ZONE_W2K;
  606. status = DnsRpc_ConvertToCurrent(
  607. &dwtype,
  608. &pzonelistDotNet->ZoneArray[ i ] );
  609. if ( status != ERROR_SUCCESS )
  610. {
  611. ASSERT( status == ERROR_SUCCESS );
  612. break;
  613. }
  614. ASSERT( dwtype == DNSSRV_TYPEID_ZONE );
  615. ++pzonelistDotNet->dwZoneCount;
  616. }
  617. break;
  618. }
  619. default:
  620. break; // This struct requires no translation.
  621. }
  622. //
  623. // Cleanup and return.
  624. //
  625. Done:
  626. if ( pdwTypeId )
  627. {
  628. *pdwTypeId = dwtypeOut;
  629. }
  630. if ( ppData )
  631. {
  632. *ppData = pdataOut;
  633. }
  634. NoTranslation:
  635. DNSDBG( STUB, (
  636. "%s: status=%d\n type in=%d out=%d\n pdata in=%p out=%p\n", fn,
  637. status,
  638. dwtypeIn,
  639. dwtypeOut,
  640. pdataIn,
  641. *ppData ));
  642. return status;
  643. } // DnsRpc_ConvertToCurrent
  644. DNS_STATUS
  645. DNS_API_FUNCTION
  646. DnsRpc_ConvertToUnversioned(
  647. IN PDWORD pdwTypeId, IN OUT
  648. IN PVOID * ppData, IN OUT
  649. IN BOOL * pfAllocatedRpcStruct OUT OPTIONAL
  650. )
  651. /*++
  652. Routine Description:
  653. Takes any DNS RPC structure as input and if necessary fabricates
  654. the old-style unversioned revision of that structure from the members
  655. of the input structure. This function is cousin to
  656. DnsRpc_ConvertToCurrent.
  657. If a new structure is allocated, the old one is freed and the pointer
  658. value at ppData is replaced. Allocated points within the old struct
  659. will be freed or copied to the new struct. Basically, the client
  660. does not have to worry about freeing any part of the old struct. When
  661. he's done with the new struct he has to free it and it's members, as
  662. usual.
  663. The main use of this function is to allow a new client to send
  664. a new RPC structure (e.g. a ZONE_CREATE structure) to an old DNS
  665. server transparently. This function will attempt to make intelligent
  666. decisions about what to do if there are large functional differences
  667. in the old and new structures.
  668. Arguments:
  669. pdwTypeId - type ID of object pointed to by ppData, value may be
  670. changed to type ID of new object at ppData
  671. ppData - pointer to object, pointer may be replaced by a pointer to
  672. a newly allocated, completed different structure as required
  673. pfAllocatedRpcStruct - if not NULL, value is set to TRUE if
  674. a new structure is allocated by this function - the should request
  675. this information if it needs to know if it should free the
  676. replaced pData pointer using MIDL_user_free()
  677. Return Value:
  678. ERROR_SUCCESS or error code. If return code is not ERROR_SUCCESS, there
  679. has been some kind of fatal error. Assume data invalid in this case.
  680. --*/
  681. {
  682. DBG_FN( "DnsRpc_ConvertToUnversioned" )
  683. DNS_STATUS status = ERROR_SUCCESS;
  684. BOOL fallocatedRpcStruct = FALSE;
  685. DWORD dwtypeIn = -1;
  686. PVOID pdataIn = NULL;
  687. DWORD dwtypeOut = -1;
  688. PVOID pdataOut = NULL;
  689. DWORD i;
  690. if ( !pdwTypeId || !ppData )
  691. {
  692. ASSERT( pdwTypeId && ppData );
  693. status = ERROR_INVALID_DATA;
  694. goto NoTranslation;
  695. }
  696. //
  697. // Shortcuts: do not translate NULL, any structure that is not
  698. // versioned, or any structure that is already in unversioned
  699. // format.
  700. //
  701. if ( *pdwTypeId <= DNSSRV_TYPEID_ZONE_LIST_W2K || *ppData == NULL )
  702. {
  703. goto NoTranslation;
  704. }
  705. dwtypeOut = dwtypeIn = *pdwTypeId;
  706. pdataOut = pdataIn = *ppData;
  707. fallocatedRpcStruct = TRUE;
  708. //
  709. // Giant switch statement of all types that can be downleveled.
  710. //
  711. switch ( dwtypeIn )
  712. {
  713. case DNSSRV_TYPEID_FORWARDERS:
  714. //
  715. // Structures are identical except for dwRpcStructureVersion.
  716. //
  717. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_FORWARDERS_W2K );
  718. RtlCopyMemory(
  719. pdataOut,
  720. ( PBYTE ) pdataIn + DNS_DOTNET_VERSION_SIZE,
  721. sizeof( DNS_RPC_FORWARDERS_W2K ) );
  722. dwtypeOut = DNSSRV_TYPEID_FORWARDERS_W2K;
  723. break;
  724. case DNSSRV_TYPEID_ZONE_CREATE:
  725. //
  726. // .NET has several additional members.
  727. //
  728. {
  729. PDNS_RPC_ZONE_CREATE_INFO_W2K pzoneOut;
  730. PDNS_RPC_ZONE_CREATE_INFO pzoneIn = pdataIn;
  731. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_CREATE_INFO_W2K );
  732. pzoneOut = pdataOut;
  733. pzoneOut->pszZoneName = pzoneIn->pszZoneName;
  734. pzoneOut->dwZoneType = pzoneIn->dwZoneType;
  735. pzoneOut->fAllowUpdate = pzoneIn->fAllowUpdate;
  736. pzoneOut->fAging = pzoneIn->fAging;
  737. pzoneOut->dwFlags = pzoneIn->dwFlags;
  738. pzoneOut->pszDataFile = pzoneIn->pszDataFile;
  739. pzoneOut->fDsIntegrated = pzoneIn->fDsIntegrated;
  740. pzoneOut->fLoadExisting = pzoneIn->fLoadExisting;
  741. pzoneOut->pszAdmin = pzoneIn->pszAdmin;
  742. pzoneOut->aipMasters = pzoneIn->aipMasters;
  743. pzoneOut->aipSecondaries = pzoneIn->aipSecondaries;
  744. pzoneOut->fSecureSecondaries = pzoneIn->fSecureSecondaries;
  745. pzoneOut->fNotifyLevel = pzoneIn->fNotifyLevel;
  746. dwtypeOut = DNSSRV_TYPEID_ZONE_CREATE_W2K;
  747. break;
  748. }
  749. case DNSSRV_TYPEID_ZONE_TYPE_RESET:
  750. //
  751. // Structures are identical except for dwRpcStructureVersion.
  752. //
  753. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_TYPE_RESET_W2K );
  754. RtlCopyMemory(
  755. pdataOut,
  756. ( PBYTE ) pdataIn + DNS_DOTNET_VERSION_SIZE,
  757. sizeof( DNS_RPC_ZONE_TYPE_RESET_W2K ) );
  758. dwtypeOut = DNSSRV_TYPEID_ZONE_TYPE_RESET_W2K;
  759. break;
  760. case DNSSRV_TYPEID_ZONE_SECONDARIES:
  761. //
  762. // Structures are identical except for dwRpcStructureVersion.
  763. //
  764. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_SECONDARIES_W2K );
  765. RtlCopyMemory(
  766. pdataOut,
  767. ( PBYTE ) pdataIn + DNS_DOTNET_VERSION_SIZE,
  768. sizeof( DNS_RPC_ZONE_SECONDARIES_W2K ) );
  769. dwtypeOut = DNSSRV_TYPEID_ZONE_SECONDARIES_W2K;
  770. break;
  771. case DNSSRV_TYPEID_ZONE_DATABASE:
  772. //
  773. // Structures are identical except for dwRpcStructureVersion.
  774. //
  775. ALLOCATE_RPC_STRUCT( pdataOut, DNS_RPC_ZONE_DATABASE_W2K );
  776. RtlCopyMemory(
  777. pdataOut,
  778. ( PBYTE ) pdataIn + DNS_DOTNET_VERSION_SIZE,
  779. sizeof( DNS_RPC_ZONE_DATABASE_W2K ) );
  780. dwtypeOut = DNSSRV_TYPEID_ZONE_DATABASE_W2K;
  781. break;
  782. default:
  783. fallocatedRpcStruct = FALSE;
  784. break; // Unknown - do nothing.
  785. }
  786. //
  787. // Cleanup and return.
  788. //
  789. Done:
  790. if ( pdwTypeId )
  791. {
  792. *pdwTypeId = dwtypeOut;
  793. }
  794. if ( ppData )
  795. {
  796. *ppData = pdataOut;
  797. }
  798. NoTranslation:
  799. if ( pfAllocatedRpcStruct )
  800. {
  801. *pfAllocatedRpcStruct = fallocatedRpcStruct;
  802. }
  803. DNSDBG( STUB, (
  804. "%s: status=%d\n type in=%d out=%d\n pdata in=%p out=%p\n", fn,
  805. status,
  806. dwtypeIn,
  807. dwtypeOut,
  808. pdataIn,
  809. *ppData ));
  810. return status;
  811. } // DnsRpc_ConvertToUnversioned
  812. //
  813. // RPC functions
  814. //
  815. DNS_STATUS
  816. DNS_API_FUNCTION
  817. DnssrvOperationEx(
  818. IN DWORD dwClientVersion,
  819. IN DWORD dwSettingFlags,
  820. IN LPCWSTR Server,
  821. IN LPCSTR pszZone,
  822. IN DWORD dwContext,
  823. IN LPCSTR pszOperation,
  824. IN DWORD dwTypeId,
  825. IN PVOID pData
  826. )
  827. {
  828. DNS_STATUS status;
  829. DNSSRV_RPC_UNION rpcData;
  830. BOOL fallocatedRpcStruct = FALSE;
  831. DECLARE_DNS_RPC_RETRY_STATE( status );
  832. if ( status != ERROR_SUCCESS )
  833. {
  834. return status;
  835. }
  836. rpcData.Null = pData;
  837. IF_DNSDBG( STUB )
  838. {
  839. DNS_PRINT((
  840. "Enter DnssrvOperationEx()\n"
  841. "\tClient ver = 0x%X\n"
  842. "\tServer = %S\n"
  843. "\tZone = %s\n"
  844. "\tContext = %p\n"
  845. "\tOperation = %s\n"
  846. "\tTypeid = %d\n",
  847. dwClientVersion,
  848. Server,
  849. pszZone,
  850. dwContext,
  851. pszOperation,
  852. dwTypeId ));
  853. IF_DNSDBG( STUB2 )
  854. {
  855. DnsDbg_RpcUnion(
  856. "pData for R_DnssrvOperationEx ",
  857. dwTypeId,
  858. rpcData.Null );
  859. }
  860. }
  861. #if 0
  862. // generate multizone context?
  863. //
  864. // DEVNOTE: get this working
  865. if ( pszZone )
  866. {
  867. dwContext = DnssrvGenerateZoneOperationContext( pszZone, dwContext );
  868. }
  869. #endif
  870. DECLARE_DNS_RPC_RETRY_LABEL()
  871. RpcTryExcept
  872. {
  873. ASSERT_DNS_RPC_RETRY_STATE_VALID();
  874. if ( DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_NEW )
  875. {
  876. status = R_DnssrvOperation2(
  877. dwClientVersion,
  878. dwSettingFlags,
  879. Server,
  880. pszZone,
  881. dwContext,
  882. pszOperation,
  883. dwTypeId,
  884. rpcData );
  885. }
  886. else
  887. {
  888. status = R_DnssrvOperation(
  889. Server,
  890. pszZone,
  891. dwContext,
  892. pszOperation,
  893. dwTypeId,
  894. rpcData );
  895. }
  896. ADVANCE_DNS_RPC_RETRY_STATE( status );
  897. IF_DNSDBG( STUB )
  898. {
  899. DNS_PRINT((
  900. "Leave R_DnssrvOperation(): status %d (%p)\n",
  901. status, status ));
  902. }
  903. }
  904. RpcExcept (1)
  905. {
  906. status = RpcExceptionCode();
  907. IF_DNSDBG( STUB )
  908. {
  909. DNS_PRINT((
  910. "RpcExcept: code = %d (%p)\n",
  911. status, status ));
  912. }
  913. //
  914. // For downlevel server, attempt to construct old-style data.
  915. //
  916. DnsRpc_ConvertToUnversioned( &dwTypeId, &pData, &fallocatedRpcStruct );
  917. rpcData.Null = pData;
  918. ADVANCE_DNS_RPC_RETRY_STATE( status );
  919. }
  920. RpcEndExcept
  921. TEST_DNS_RPC_RETRY();
  922. printExtendedRpcErrorInfo( status );
  923. if ( fallocatedRpcStruct )
  924. {
  925. MIDL_user_free( pData );
  926. }
  927. return status;
  928. }
  929. DNS_STATUS
  930. DNS_API_FUNCTION
  931. DnssrvQueryEx(
  932. IN DWORD dwClientVersion,
  933. IN DWORD dwSettingFlags,
  934. IN LPCWSTR Server,
  935. IN LPCSTR pszZone,
  936. IN LPCSTR pszQuery,
  937. OUT PDWORD pdwTypeId,
  938. OUT PVOID * ppData
  939. )
  940. {
  941. DNS_STATUS status;
  942. DECLARE_DNS_RPC_RETRY_STATE( status );
  943. if ( status != ERROR_SUCCESS )
  944. {
  945. return status;
  946. }
  947. IF_DNSDBG( STUB )
  948. {
  949. DNS_PRINT((
  950. "Enter DnssrvQuery()\n"
  951. "\tClient ver = 0x%X\n"
  952. "\tServer = %S\n"
  953. "\tZone = %s\n"
  954. "\tQuery = %s\n",
  955. dwClientVersion,
  956. Server,
  957. pszZone,
  958. pszQuery ));
  959. DNSDBG( STUB2, (
  960. "\tpdwTypeId = %p\n"
  961. "\tppData = %p\n"
  962. "\t*pdwTypeId = %d\n"
  963. "\t*ppData = %p\n",
  964. pdwTypeId,
  965. ppData,
  966. *pdwTypeId,
  967. *ppData ));
  968. }
  969. if ( !pszQuery || !ppData || !pdwTypeId )
  970. {
  971. DNS_ASSERT( FALSE );
  972. return( ERROR_INVALID_PARAMETER );
  973. }
  974. //
  975. // RPC sees ppData as actually a PTR to a UNION structure, and
  976. // for pointer type returns, would like to copy the data back into the
  977. // memory pointed at by the current value of the pointer.
  978. //
  979. // This is not what we want, we just want to capture a pointer to
  980. // the returned data block. To do this init the pointer value to
  981. // be NULL, so RPC will then allocate memory of all pointer types
  982. // in the UNION.
  983. //
  984. *ppData = NULL;
  985. DECLARE_DNS_RPC_RETRY_LABEL()
  986. RpcTryExcept
  987. {
  988. ASSERT_DNS_RPC_RETRY_STATE_VALID();
  989. if ( DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_NEW )
  990. {
  991. status = R_DnssrvQuery2(
  992. dwClientVersion,
  993. dwSettingFlags,
  994. Server,
  995. pszZone,
  996. pszQuery,
  997. pdwTypeId,
  998. ( DNSSRV_RPC_UNION * ) ppData );
  999. }
  1000. else
  1001. {
  1002. status = R_DnssrvQuery(
  1003. Server,
  1004. pszZone,
  1005. pszQuery,
  1006. pdwTypeId,
  1007. ( DNSSRV_RPC_UNION * ) ppData );
  1008. }
  1009. ADVANCE_DNS_RPC_RETRY_STATE( status );
  1010. IF_DNSDBG( STUB )
  1011. {
  1012. DNS_PRINT((
  1013. "Leave R_DnssrvQuery(): status %d (%p)\n"
  1014. "\tTypeId = %d\n"
  1015. "\tDataPtr = %p\n",
  1016. status, status,
  1017. *pdwTypeId,
  1018. *ppData ));
  1019. if ( ppData )
  1020. {
  1021. DnsDbg_RpcUnion(
  1022. "After R_DnssrvQuery ...\n",
  1023. *pdwTypeId,
  1024. *ppData );
  1025. }
  1026. }
  1027. }
  1028. RpcExcept (1)
  1029. {
  1030. status = RpcExceptionCode();
  1031. IF_DNSDBG( STUB )
  1032. {
  1033. DNS_PRINT((
  1034. "RpcExcept: code = %d (%p)\n",
  1035. status, status ));
  1036. }
  1037. ADVANCE_DNS_RPC_RETRY_STATE( status );
  1038. }
  1039. RpcEndExcept
  1040. TEST_DNS_RPC_RETRY();
  1041. //
  1042. // Upgrade old structure to new.
  1043. //
  1044. printExtendedRpcErrorInfo( status );
  1045. if ( status == ERROR_SUCCESS )
  1046. {
  1047. status = DnsRpc_ConvertToCurrent( pdwTypeId, ppData );
  1048. }
  1049. return status;
  1050. }
  1051. DNS_STATUS
  1052. DNS_API_FUNCTION
  1053. DnssrvComplexOperationEx(
  1054. IN DWORD dwClientVersion,
  1055. IN DWORD dwSettingFlags,
  1056. IN LPCWSTR Server,
  1057. IN LPCSTR pszZone,
  1058. IN LPCSTR pszOperation,
  1059. IN DWORD dwTypeIn,
  1060. IN PVOID pDataIn,
  1061. OUT PDWORD pdwTypeOut,
  1062. OUT PVOID * ppDataOut
  1063. )
  1064. {
  1065. DNS_STATUS status;
  1066. DNSSRV_RPC_UNION rpcData;
  1067. DECLARE_DNS_RPC_RETRY_STATE( status );
  1068. if ( status != ERROR_SUCCESS )
  1069. {
  1070. return status;
  1071. }
  1072. rpcData.Null = pDataIn;
  1073. IF_DNSDBG( STUB )
  1074. {
  1075. DNS_PRINT((
  1076. "Enter DnssrvComplexOperation()\n"
  1077. "\tClient ver = 0x%X\n"
  1078. "\tServer = %S\n"
  1079. "\tZone = %s\n"
  1080. "\tOperation = %s\n"
  1081. "\tTypeIn = %d\n",
  1082. dwClientVersion,
  1083. Server,
  1084. pszZone,
  1085. pszOperation,
  1086. dwTypeIn ));
  1087. IF_DNSDBG( STUB2 )
  1088. {
  1089. DnsDbg_RpcUnion(
  1090. "pData for R_DnssrvOperation ",
  1091. dwTypeIn,
  1092. rpcData.Null );
  1093. DNS_PRINT((
  1094. "\tpdwTypeOut = %p\n"
  1095. "\tppDataOut = %p\n"
  1096. "\t*pdwTypeOut = %d\n"
  1097. "\t*ppDataOut = %p\n",
  1098. pdwTypeOut,
  1099. ppDataOut,
  1100. *pdwTypeOut,
  1101. *ppDataOut ));
  1102. }
  1103. }
  1104. if ( !pszOperation || !ppDataOut || !pdwTypeOut )
  1105. {
  1106. DNS_ASSERT( FALSE );
  1107. return( ERROR_INVALID_PARAMETER );
  1108. }
  1109. //
  1110. // RPC sees ppDataOut as actually a PTR to a UNION structure, and
  1111. // for pointer type returns, would like to copy the data back into
  1112. // the memory pointed at by the current value of the pointer.
  1113. //
  1114. // This is not what we want, we just want to capture a pointer to
  1115. // the returned data block. To do this init the pointer value to
  1116. // be NULL, so RPC will then allocate memory of all pointer types
  1117. // in the UNION.
  1118. //
  1119. *ppDataOut = NULL;
  1120. DECLARE_DNS_RPC_RETRY_LABEL()
  1121. RpcTryExcept
  1122. {
  1123. ASSERT_DNS_RPC_RETRY_STATE_VALID();
  1124. if ( DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_NEW )
  1125. {
  1126. status = R_DnssrvComplexOperation2(
  1127. dwClientVersion,
  1128. dwSettingFlags,
  1129. Server,
  1130. pszZone,
  1131. pszOperation,
  1132. dwTypeIn,
  1133. rpcData,
  1134. pdwTypeOut,
  1135. ( DNSSRV_RPC_UNION * ) ppDataOut );
  1136. }
  1137. else
  1138. {
  1139. status = R_DnssrvComplexOperation(
  1140. Server,
  1141. pszZone,
  1142. pszOperation,
  1143. dwTypeIn,
  1144. rpcData,
  1145. pdwTypeOut,
  1146. ( DNSSRV_RPC_UNION * ) ppDataOut );
  1147. }
  1148. ADVANCE_DNS_RPC_RETRY_STATE( status );
  1149. IF_DNSDBG( STUB )
  1150. {
  1151. DNS_PRINT((
  1152. "Leave R_DnssrvComplexOperation(): status %d (%p)\n"
  1153. "\tTypeId = %d\n"
  1154. "\tDataPtr = %p\n",
  1155. status, status,
  1156. *pdwTypeOut,
  1157. *ppDataOut ));
  1158. if ( ppDataOut )
  1159. {
  1160. DnsDbg_RpcUnion(
  1161. "After R_DnssrvQuery ...\n",
  1162. *pdwTypeOut,
  1163. *ppDataOut );
  1164. }
  1165. }
  1166. }
  1167. RpcExcept (1)
  1168. {
  1169. status = RpcExceptionCode();
  1170. IF_DNSDBG( STUB )
  1171. {
  1172. DNS_PRINT((
  1173. "RpcExcept: code = %d (%p)\n",
  1174. status, status ));
  1175. }
  1176. ADVANCE_DNS_RPC_RETRY_STATE( status );
  1177. }
  1178. RpcEndExcept
  1179. TEST_DNS_RPC_RETRY();
  1180. printExtendedRpcErrorInfo( status );
  1181. //
  1182. // Upgrade old structure to new.
  1183. //
  1184. if ( status == ERROR_SUCCESS )
  1185. {
  1186. status = DnsRpc_ConvertToCurrent( pdwTypeOut, ppDataOut );
  1187. }
  1188. return status;
  1189. }
  1190. DNS_STATUS
  1191. DNS_API_FUNCTION
  1192. DnssrvEnumRecordsEx(
  1193. IN DWORD dwClientVersion,
  1194. IN DWORD dwSettingFlags,
  1195. IN LPCWSTR Server,
  1196. IN LPCSTR pszZoneName,
  1197. IN LPCSTR pszNodeName,
  1198. IN LPCSTR pszStartChild,
  1199. IN WORD wRecordType,
  1200. IN DWORD dwSelectFlag,
  1201. IN LPCSTR pszFilterStart,
  1202. IN LPCSTR pszFilterStop,
  1203. IN OUT PDWORD pdwBufferLength,
  1204. OUT PBYTE * ppBuffer
  1205. )
  1206. /*++
  1207. Routine Description:
  1208. Stub for EnumRecords API.
  1209. Note, this matches DnssrvEnumRecords() API exactly.
  1210. The "Stub" suffix is attached to distinguish from the actual
  1211. DnssrvEnumRecords() (remote.c) which handles NT4 server compatibility.
  1212. When that is no longer desired, that routine may be eliminated and
  1213. this the "Stub" suffix removed from this routine.
  1214. Arguments:
  1215. Return Value:
  1216. ERROR_SUCCESS on successful enumeration.
  1217. ERROR_MORE_DATA when buffer full and more data remains.
  1218. ErrorCode on failure.
  1219. --*/
  1220. {
  1221. DNS_STATUS status;
  1222. DECLARE_DNS_RPC_RETRY_STATE( status );
  1223. if ( status != ERROR_SUCCESS )
  1224. {
  1225. return status;
  1226. }
  1227. DNSDBG( STUB, (
  1228. "Enter DnssrvEnumRecords()\n"
  1229. "\tClient ver = 0x%X\n"
  1230. "\tServer = %S\n"
  1231. "\tpszZoneName = %s\n"
  1232. "\tpszNodeName = %s\n"
  1233. "\tpszStartChild = %s\n"
  1234. "\twRecordType = %d\n"
  1235. "\tdwSelectFlag = %p\n"
  1236. "\tpszFilterStart = %s\n"
  1237. "\tpszFilterStop = %s\n"
  1238. "\tpdwBufferLength = %p\n"
  1239. "\tppBuffer = %p\n",
  1240. dwClientVersion,
  1241. Server,
  1242. pszZoneName,
  1243. pszNodeName,
  1244. pszStartChild,
  1245. wRecordType,
  1246. dwSelectFlag,
  1247. pszFilterStart,
  1248. pszFilterStop,
  1249. pdwBufferLength,
  1250. ppBuffer ));
  1251. DECLARE_DNS_RPC_RETRY_LABEL()
  1252. RpcTryExcept
  1253. {
  1254. // clear ptr for safety, we don't want to free any bogus memory
  1255. *ppBuffer = NULL;
  1256. ASSERT_DNS_RPC_RETRY_STATE_VALID();
  1257. if ( DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_NEW )
  1258. {
  1259. status = R_DnssrvEnumRecords2(
  1260. dwClientVersion,
  1261. dwSettingFlags,
  1262. Server,
  1263. pszZoneName,
  1264. pszNodeName,
  1265. pszStartChild,
  1266. wRecordType,
  1267. dwSelectFlag,
  1268. pszFilterStart,
  1269. pszFilterStop,
  1270. pdwBufferLength,
  1271. ppBuffer );
  1272. }
  1273. else
  1274. {
  1275. status = R_DnssrvEnumRecords(
  1276. Server,
  1277. pszZoneName,
  1278. pszNodeName,
  1279. pszStartChild,
  1280. wRecordType,
  1281. dwSelectFlag,
  1282. pszFilterStart,
  1283. pszFilterStop,
  1284. pdwBufferLength,
  1285. ppBuffer );
  1286. }
  1287. ADVANCE_DNS_RPC_RETRY_STATE( status );
  1288. IF_DNSDBG( STUB )
  1289. {
  1290. DNS_PRINT((
  1291. "R_DnssrvEnumRecords: try = %d status = %d / %p\n",
  1292. DNS_RPC_RETRY_STATE(),
  1293. status,
  1294. status ));
  1295. if ( status == ERROR_SUCCESS || status == ERROR_MORE_DATA )
  1296. {
  1297. DnsDbg_RpcRecordsInBuffer(
  1298. "Returned records: ",
  1299. *pdwBufferLength,
  1300. *ppBuffer );
  1301. }
  1302. }
  1303. }
  1304. RpcExcept (1)
  1305. {
  1306. status = RpcExceptionCode();
  1307. IF_DNSDBG( STUB )
  1308. {
  1309. DNS_PRINT((
  1310. "RpcExcept: code = %d / %p\n",
  1311. status,
  1312. status ));
  1313. }
  1314. ADVANCE_DNS_RPC_RETRY_STATE( status );
  1315. }
  1316. RpcEndExcept
  1317. TEST_DNS_RPC_RETRY();
  1318. printExtendedRpcErrorInfo( status );
  1319. return status;
  1320. }
  1321. DNS_STATUS
  1322. DNS_API_FUNCTION
  1323. DnssrvUpdateRecordEx(
  1324. IN DWORD dwClientVersion,
  1325. IN DWORD dwSettingFlags,
  1326. IN LPCWSTR Server,
  1327. IN LPCSTR pszZoneName,
  1328. IN LPCSTR pszNodeName,
  1329. IN PDNS_RPC_RECORD pAddRecord,
  1330. IN PDNS_RPC_RECORD pDeleteRecord
  1331. )
  1332. /*++
  1333. Routine Description:
  1334. Stub for UpdateRecords API.
  1335. Arguments:
  1336. Return Value:
  1337. ERROR_SUCCESS on successful enumeration.
  1338. ErrorCode on failure.
  1339. --*/
  1340. {
  1341. DNS_STATUS status;
  1342. DECLARE_DNS_RPC_RETRY_STATE( status );
  1343. if ( status != ERROR_SUCCESS )
  1344. {
  1345. return status;
  1346. }
  1347. DNSDBG( STUB, (
  1348. "Enter R_DnssrvUpdateRecord()\n"
  1349. "\tClient ver = 0x%X\n"
  1350. "\tServer = %S\n"
  1351. "\tpszZoneName = %s\n"
  1352. "\tpszNodeName = %s\n"
  1353. "\tpAddRecord = %p\n"
  1354. "\tpDeleteRecord = %p\n",
  1355. dwClientVersion,
  1356. Server,
  1357. pszZoneName,
  1358. pszNodeName,
  1359. pAddRecord,
  1360. pDeleteRecord ));
  1361. DECLARE_DNS_RPC_RETRY_LABEL()
  1362. RpcTryExcept
  1363. {
  1364. ASSERT_DNS_RPC_RETRY_STATE_VALID();
  1365. if ( DNS_RPC_RETRY_STATE() == DNS_RPC_TRY_NEW )
  1366. {
  1367. status = R_DnssrvUpdateRecord2(
  1368. dwClientVersion,
  1369. dwSettingFlags,
  1370. Server,
  1371. pszZoneName,
  1372. pszNodeName,
  1373. pAddRecord,
  1374. pDeleteRecord );
  1375. }
  1376. else
  1377. {
  1378. status = R_DnssrvUpdateRecord(
  1379. Server,
  1380. pszZoneName,
  1381. pszNodeName,
  1382. pAddRecord,
  1383. pDeleteRecord );
  1384. }
  1385. ADVANCE_DNS_RPC_RETRY_STATE( status );
  1386. DNSDBG( STUB, (
  1387. "R_DnssrvUpdateRecord: status = %d / %p\n",
  1388. status, status ));
  1389. }
  1390. RpcExcept (1)
  1391. {
  1392. status = RpcExceptionCode();
  1393. DNSDBG( STUB, (
  1394. "RpcExcept: code = %d / %p\n",
  1395. status, status ));
  1396. ADVANCE_DNS_RPC_RETRY_STATE( status );
  1397. }
  1398. RpcEndExcept
  1399. TEST_DNS_RPC_RETRY();
  1400. printExtendedRpcErrorInfo( status );
  1401. return status;
  1402. }
  1403. //
  1404. // End stub.c
  1405. //