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.

905 lines
23 KiB

  1. #include <precomp.h>
  2. #include "wzcsvc.h"
  3. #include "tracing.h"
  4. #include "utils.h"
  5. #include "intflist.h"
  6. #include "rpcsrv.h"
  7. #include "database.h"
  8. extern HASH sessionHash;
  9. //-------------------------------------------------
  10. // Globals used for the RPC interface
  11. BOOL g_bRpcStarted = FALSE;
  12. PSECURITY_DESCRIPTOR g_pSecurityDescr = NULL;
  13. GENERIC_MAPPING g_Mapping = {
  14. WZC_READ,
  15. WZC_WRITE,
  16. WZC_EXECUTE,
  17. WZC_ALL_ACCESS};
  18. //-------------------------------------------------
  19. // Initialize the security settings for the RPC API
  20. DWORD
  21. WZCSvcInitRPCSecurity()
  22. {
  23. DWORD dwErr = ERROR_SUCCESS;
  24. NTSTATUS ntStatus;
  25. ACE_DATA AceData[6] = {
  26. {ACCESS_ALLOWED_ACE_TYPE, 0, 0, WZC_ACCESS_SET|WZC_ACCESS_QUERY, &LocalSystemSid},
  27. {ACCESS_ALLOWED_ACE_TYPE, 0, 0, WZC_ACCESS_SET|WZC_ACCESS_QUERY, &AliasAdminsSid},
  28. {ACCESS_ALLOWED_ACE_TYPE, 0, 0, WZC_ACCESS_SET|WZC_ACCESS_QUERY, &AliasAccountOpsSid},
  29. {ACCESS_ALLOWED_ACE_TYPE, 0, 0, WZC_ACCESS_SET|WZC_ACCESS_QUERY, &AliasSystemOpsSid},
  30. {ACCESS_ALLOWED_ACE_TYPE, 0, 0, WZC_ACCESS_SET|WZC_ACCESS_QUERY, &AliasUsersSid},
  31. // for now (WinXP Client RTM) the decision was made to let everybody party, but based on
  32. // the acl below. Later, the security schema won't change by default, but support will be
  33. // added allowing admins to tighten up the access to the service RPC APIs.
  34. {ACCESS_ALLOWED_ACE_TYPE, 0, 0, WZC_ACCESS_SET|WZC_ACCESS_QUERY, &WorldSid}};
  35. DbgPrint((TRC_TRACK, "[WZCSvcInitRPCSecurity"));
  36. // create the well known SIDs;
  37. dwErr = RtlNtStatusToDosError(
  38. NetpCreateWellKnownSids(NULL)
  39. );
  40. DbgAssert((dwErr == ERROR_SUCCESS, "Error %d creating the well known Sids!", dwErr));
  41. // create the security object.
  42. if (dwErr == ERROR_SUCCESS)
  43. {
  44. dwErr = RtlNtStatusToDosError(
  45. NetpCreateSecurityObject(
  46. AceData,
  47. sizeof(AceData)/sizeof(ACE_DATA),
  48. NULL,
  49. NULL,
  50. &g_Mapping,
  51. &g_pSecurityDescr)
  52. );
  53. DbgAssert((dwErr == ERROR_SUCCESS, "Error %d creating the global security object!", dwErr));
  54. }
  55. DbgPrint((TRC_TRACK, "WZCSvcInitRPCSecurity]=%d", dwErr));
  56. return dwErr;
  57. }
  58. //-------------------------------------------------
  59. // Check the access for the particular access mask provided
  60. DWORD
  61. WZCSvcCheckRPCAccess(DWORD dwAccess)
  62. {
  63. DWORD dwErr = ERROR_SUCCESS;
  64. if (g_pSecurityDescr != NULL)
  65. {
  66. dwErr = NetpAccessCheckAndAudit(
  67. _T("WZCSVC"),
  68. _T("WZCSVC"),
  69. g_pSecurityDescr,
  70. dwAccess,
  71. &g_Mapping);
  72. DbgPrint((TRC_GENERIC, ">>> Security check reports err=%d.", dwErr));
  73. }
  74. return dwErr;
  75. }
  76. //-------------------------------------------------
  77. // Check the validity of a RAW_DATA pointer
  78. DWORD
  79. WZCSvcCheckParamRawData(PRAW_DATA prd)
  80. {
  81. DWORD dwErr = ERROR_SUCCESS;
  82. if (prd != NULL)
  83. {
  84. if (prd->dwDataLen != 0 && prd->pData == NULL)
  85. dwErr = ERROR_INVALID_PARAMETER;
  86. }
  87. return dwErr;
  88. }
  89. //-------------------------------------------------
  90. // Check the validity of an SSID embedded in a RAW_DATA pointer
  91. DWORD
  92. WZCSvcCheckSSID(PNDIS_802_11_SSID pndSSID, UINT nBytes)
  93. {
  94. DWORD dwErr = ERROR_SUCCESS;
  95. if (pndSSID != NULL)
  96. {
  97. if (FIELD_OFFSET(NDIS_802_11_SSID, Ssid) + pndSSID->SsidLength > nBytes)
  98. dwErr = ERROR_INVALID_PARAMETER;
  99. }
  100. return dwErr;
  101. }
  102. //-------------------------------------------------
  103. // Check the validity of a list of configurations embedded in a RAW_DATA pointer
  104. DWORD
  105. WZCSvcCheckConfig(PWZC_WLAN_CONFIG pwzcConfig, UINT nBytes)
  106. {
  107. DWORD dwErr = ERROR_SUCCESS;
  108. if (pwzcConfig != NULL)
  109. {
  110. if (pwzcConfig->Length > nBytes ||
  111. pwzcConfig->Length != sizeof(WZC_WLAN_CONFIG))
  112. dwErr = ERROR_INVALID_PARAMETER;
  113. if (dwErr == ERROR_SUCCESS)
  114. dwErr = WZCSvcCheckSSID(&pwzcConfig->Ssid, sizeof(NDIS_802_11_SSID));
  115. if (dwErr == ERROR_SUCCESS &&
  116. pwzcConfig->KeyLength > WZCCTL_MAX_WEPK_MATERIAL)
  117. dwErr = ERROR_INVALID_PARAMETER;
  118. }
  119. return dwErr;
  120. }
  121. //-------------------------------------------------
  122. // Check the validity of a list of configurations embedded in a RAW_DATA pointer
  123. DWORD
  124. WZCSvcCheckConfigList(PWZC_802_11_CONFIG_LIST pwzcList, UINT nBytes)
  125. {
  126. DWORD dwErr = ERROR_SUCCESS;
  127. if (pwzcList != NULL)
  128. {
  129. UINT i;
  130. if (nBytes < FIELD_OFFSET(WZC_802_11_CONFIG_LIST, Config))
  131. dwErr = ERROR_INVALID_PARAMETER;
  132. nBytes -= FIELD_OFFSET(WZC_802_11_CONFIG_LIST, Config);
  133. if (dwErr == ERROR_SUCCESS &&
  134. ((pwzcList->NumberOfItems * sizeof(WZC_WLAN_CONFIG) > nBytes) ||
  135. (pwzcList->Index > pwzcList->NumberOfItems)
  136. )
  137. )
  138. dwErr = ERROR_INVALID_PARAMETER;
  139. for (i = 0; i < pwzcList->NumberOfItems && dwErr == ERROR_SUCCESS; i++)
  140. dwErr = WZCSvcCheckConfig(&(pwzcList->Config[i]), sizeof(WZC_WLAN_CONFIG));
  141. }
  142. return dwErr;
  143. }
  144. //-------------------------------------------------
  145. // Check the validity of the "input" fields from the INTF_ENTRY.
  146. DWORD
  147. WZCSvcCheckParamIntfEntry(PINTF_ENTRY pIntfEntry)
  148. {
  149. DWORD dwErr = ERROR_SUCCESS;
  150. if (pIntfEntry != NULL)
  151. {
  152. if (dwErr == ERROR_SUCCESS)
  153. dwErr = WZCSvcCheckParamRawData(&pIntfEntry->rdSSID);
  154. if (dwErr == ERROR_SUCCESS)
  155. dwErr = WZCSvcCheckParamRawData(&pIntfEntry->rdBSSID);
  156. if (dwErr == ERROR_SUCCESS)
  157. dwErr = WZCSvcCheckParamRawData(&pIntfEntry->rdStSSIDList);
  158. if (dwErr == ERROR_SUCCESS)
  159. dwErr = WZCSvcCheckConfigList(
  160. (PWZC_802_11_CONFIG_LIST)pIntfEntry->rdStSSIDList.pData,
  161. pIntfEntry->rdStSSIDList.dwDataLen);
  162. if (dwErr == ERROR_SUCCESS)
  163. dwErr = WZCSvcCheckParamRawData(&pIntfEntry->rdCtrlData);
  164. }
  165. return dwErr;
  166. }
  167. //-------------------------------------------------
  168. // Cleanup whatever data was used for RPC security settings
  169. DWORD
  170. WZCSvcTermRPCSecurity()
  171. {
  172. DWORD dwErr = ERROR_SUCCESS;
  173. DbgPrint((TRC_TRACK, "[WZCSvcTermRPCSecurity"));
  174. dwErr = RtlNtStatusToDosError(NetpDeleteSecurityObject(&g_pSecurityDescr));
  175. DbgAssert((dwErr == ERROR_SUCCESS, "Failed to delete the global security descriptor!"));
  176. g_pSecurityDescr = NULL;
  177. NetpFreeWellKnownSids();
  178. DbgPrint((TRC_TRACK, "WZCSvcTermRPCSecurity]=%d", dwErr));
  179. return dwErr;
  180. }
  181. RPC_STATUS CallbackCheckLocal(
  182. IN RPC_IF_HANDLE *Interface,
  183. IN void *Context)
  184. {
  185. RPC_STATUS rpcStat = RPC_S_OK;
  186. LPTSTR pBinding = NULL;
  187. LPTSTR pProtSeq = NULL;
  188. rpcStat = RpcBindingToStringBinding(Context, &pBinding);
  189. if (rpcStat == RPC_S_OK)
  190. {
  191. rpcStat = RpcStringBindingParse(
  192. pBinding,
  193. NULL,
  194. &pProtSeq,
  195. NULL,
  196. NULL,
  197. NULL);
  198. }
  199. if (rpcStat == RPC_S_OK)
  200. {
  201. if (_tcsicmp((LPCTSTR)pProtSeq, _T("ncalrpc")) != 0)
  202. rpcStat = RPC_S_ACCESS_DENIED;
  203. }
  204. if (pBinding != NULL)
  205. RpcStringFree(&pBinding);
  206. if (pProtSeq != NULL)
  207. RpcStringFree(&pProtSeq);
  208. return rpcStat;
  209. }
  210. DWORD
  211. WZCSvcStartRPCServer()
  212. {
  213. DWORD dwStatus = RPC_S_OK;
  214. DbgPrint((TRC_TRACK, "[WZCSvcStartRPCServer"));
  215. if (dwStatus == RPC_S_OK)
  216. {
  217. dwStatus = RpcServerUseProtseqEp(
  218. L"ncalrpc",
  219. 10,
  220. L"wzcsvc",
  221. NULL);
  222. if (dwStatus == RPC_S_DUPLICATE_ENDPOINT)
  223. dwStatus = RPC_S_OK;
  224. }
  225. if (dwStatus == RPC_S_OK)
  226. {
  227. dwStatus = RpcServerRegisterIfEx(
  228. winwzc_ServerIfHandle,
  229. 0,
  230. 0,
  231. RPC_IF_ALLOW_SECURE_ONLY, // WZCSAPI is using RPC_C_PROTECT_LEVEL_PKT_PRIVACY
  232. 0, // ignored for non auto-listen interfaces
  233. CallbackCheckLocal);
  234. }
  235. if (dwStatus == RPC_S_OK)
  236. {
  237. dwStatus = RpcServerRegisterAuthInfo(
  238. 0,
  239. RPC_C_AUTHN_WINNT,
  240. 0,
  241. 0);
  242. }
  243. if (dwStatus == RPC_S_OK)
  244. {
  245. dwStatus = RpcServerRegisterAuthInfo(
  246. 0,
  247. RPC_C_AUTHN_GSS_KERBEROS,
  248. 0,
  249. 0);
  250. }
  251. if (dwStatus == RPC_S_OK)
  252. {
  253. dwStatus = RpcServerRegisterAuthInfo(
  254. 0,
  255. RPC_C_AUTHN_GSS_NEGOTIATE,
  256. 0,
  257. 0);
  258. }
  259. if (dwStatus == RPC_S_OK)
  260. {
  261. dwStatus = RpcServerListen(
  262. 3,
  263. RPC_C_LISTEN_MAX_CALLS_DEFAULT,
  264. TRUE);
  265. if (dwStatus == RPC_S_ALREADY_LISTENING)
  266. dwStatus = RPC_S_OK;
  267. }
  268. if (dwStatus != RPC_S_OK)
  269. {
  270. RpcServerUnregisterIfEx(
  271. winwzc_ServerIfHandle,
  272. 0,
  273. 0);
  274. }
  275. g_bRpcStarted = (dwStatus == RPC_S_OK);
  276. WZCSvcInitRPCSecurity();
  277. DbgPrint((TRC_TRACK, "WZCSvcStartRPCServer]=%d", dwStatus));
  278. return (dwStatus);
  279. }
  280. DWORD
  281. WZCSvcStopRPCServer()
  282. {
  283. DWORD dwStatus = RPC_S_OK;
  284. DbgPrint((TRC_TRACK, "[WZCSvcStopRPCServer"));
  285. if (g_bRpcStarted)
  286. {
  287. g_bRpcStarted = FALSE;
  288. WZCSvcTermRPCSecurity();
  289. dwStatus = RpcServerUnregisterIfEx(
  290. winwzc_ServerIfHandle,
  291. 0,
  292. 0);
  293. // don't stop RPC from listening - other services could rely on this
  294. //RpcMgmtStopServerListening(0);
  295. }
  296. DbgPrint((TRC_TRACK, "WZCSvcStopRPCServer]=%d", dwStatus));
  297. return (dwStatus);
  298. }
  299. DWORD
  300. RpcEnumInterfaces(
  301. STRING_HANDLE pSrvAddr,
  302. PINTFS_KEY_TABLE pIntfsTable)
  303. {
  304. DWORD dwErr = ERROR_SUCCESS;
  305. DWORD dwNumIntfs;
  306. InterlockedIncrement(&g_nThreads);
  307. DbgPrint((TRC_TRACK, "[RpcEnumInterfaces"));
  308. dwErr = WZCSvcCheckRPCAccess(WZC_ACCESS_QUERY);
  309. if (dwErr == ERROR_SUCCESS)
  310. {
  311. dwNumIntfs = LstNumInterfaces();
  312. DbgPrint((TRC_GENERIC,
  313. "Num interfaces = %d",
  314. dwNumIntfs));
  315. if (dwNumIntfs == 0)
  316. goto exit;
  317. pIntfsTable->pIntfs = RpcCAlloc(dwNumIntfs*sizeof(INTF_KEY_ENTRY));
  318. if (pIntfsTable->pIntfs == NULL)
  319. {
  320. dwErr = GetLastError();
  321. goto exit;
  322. }
  323. dwErr = LstGetIntfsKeyInfo(pIntfsTable->pIntfs, &dwNumIntfs);
  324. if (dwErr != ERROR_SUCCESS || dwNumIntfs == 0)
  325. {
  326. RpcFree(pIntfsTable->pIntfs);
  327. pIntfsTable->pIntfs = NULL;
  328. goto exit;
  329. }
  330. pIntfsTable->dwNumIntfs = dwNumIntfs;
  331. for (dwNumIntfs = 0; dwNumIntfs < pIntfsTable->dwNumIntfs; dwNumIntfs++)
  332. {
  333. DbgPrint((TRC_GENERIC,
  334. "Intf %d:\t%S",
  335. dwNumIntfs,
  336. pIntfsTable->pIntfs[dwNumIntfs].wszGuid == NULL ?
  337. L"(null)" :
  338. pIntfsTable->pIntfs[dwNumIntfs].wszGuid));
  339. }
  340. }
  341. exit:
  342. DbgPrint((TRC_TRACK, "RpcEnumInterfaces]=%d", dwErr));
  343. InterlockedDecrement(&g_nThreads);
  344. return dwErr;
  345. }
  346. DWORD
  347. RpcQueryInterface(
  348. STRING_HANDLE pSrvAddr,
  349. DWORD dwInFlags,
  350. PINTF_ENTRY pIntfEntry,
  351. LPDWORD pdwOutFlags)
  352. {
  353. DWORD dwErr = ERROR_SUCCESS;
  354. InterlockedIncrement(&g_nThreads);
  355. DbgPrint((TRC_TRACK, "[RpcQueryInterface(0x%x,%S)", dwInFlags, pIntfEntry->wszGuid));
  356. dwErr = WZCSvcCheckRPCAccess(WZC_ACCESS_QUERY);
  357. if (dwErr == ERROR_SUCCESS)
  358. {
  359. dwErr = LstQueryInterface(dwInFlags, pIntfEntry, pdwOutFlags);
  360. }
  361. DbgPrint((TRC_TRACK, "RpcQueryInterface]=%d", dwErr));
  362. InterlockedDecrement(&g_nThreads);
  363. return dwErr;
  364. }
  365. DWORD
  366. RpcSetInterface(
  367. STRING_HANDLE pSrvAddr,
  368. DWORD dwInFlags,
  369. PINTF_ENTRY pIntfEntry,
  370. LPDWORD pdwOutFlags)
  371. {
  372. DWORD dwErr = ERROR_SUCCESS;
  373. InterlockedIncrement(&g_nThreads);
  374. DbgPrint((TRC_TRACK, "[RpcSetInterface(0x%x,%S)", dwInFlags, pIntfEntry->wszGuid));
  375. dwErr = WZCSvcCheckRPCAccess(WZC_ACCESS_SET);
  376. if (dwErr == ERROR_SUCCESS)
  377. {
  378. dwErr = WZCSvcCheckParamIntfEntry(pIntfEntry);
  379. }
  380. if (dwErr == ERROR_SUCCESS)
  381. {
  382. dwErr = LstSetInterface(dwInFlags, pIntfEntry, pdwOutFlags);
  383. }
  384. DbgPrint((TRC_TRACK, "RpcSetInterface]=%d", dwErr));
  385. InterlockedDecrement(&g_nThreads);
  386. return dwErr;
  387. }
  388. DWORD
  389. RpcRefreshInterface(
  390. STRING_HANDLE pSrvAddr,
  391. DWORD dwInFlags,
  392. PINTF_ENTRY pIntfEntry,
  393. LPDWORD pdwOutFlags)
  394. {
  395. DWORD dwErr = ERROR_SUCCESS;
  396. InterlockedIncrement(&g_nThreads);
  397. DbgPrint((TRC_TRACK, "[RpcRefreshInterface(0x%x,%S)", dwInFlags, pIntfEntry->wszGuid));
  398. dwErr = WZCSvcCheckRPCAccess(WZC_ACCESS_SET);
  399. if (dwErr == ERROR_SUCCESS)
  400. {
  401. dwErr = LstRefreshInterface(dwInFlags, pIntfEntry, pdwOutFlags);
  402. }
  403. DbgPrint((TRC_TRACK, "RpcRefreshInterface]=%d", dwErr));
  404. InterlockedDecrement(&g_nThreads);
  405. return dwErr;
  406. }
  407. DWORD
  408. RpcQueryContext(
  409. STRING_HANDLE pSrvAddr,
  410. DWORD dwInFlags,
  411. PWZC_CONTEXT pContext,
  412. LPDWORD pdwOutFlags)
  413. {
  414. DWORD dwErr = ERROR_SUCCESS;
  415. InterlockedIncrement(&g_nThreads);
  416. DbgPrint((TRC_TRACK, "[RpcQueryContext(0x%x)", dwInFlags));
  417. dwErr = WZCSvcCheckRPCAccess(WZC_ACCESS_QUERY);
  418. if (dwErr == ERROR_SUCCESS)
  419. {
  420. dwErr = WzcContextQuery(dwInFlags, pContext, pdwOutFlags);
  421. }
  422. DbgPrint((TRC_TRACK, "RpcQueryContext]=%d", dwErr));
  423. InterlockedDecrement(&g_nThreads);
  424. return dwErr;
  425. }
  426. DWORD
  427. RpcSetContext(
  428. STRING_HANDLE pSrvAddr,
  429. DWORD dwInFlags,
  430. PWZC_CONTEXT pContext,
  431. LPDWORD pdwOutFlags)
  432. {
  433. DWORD dwErr = ERROR_SUCCESS;
  434. BOOL bLogEnabled = FALSE;
  435. InterlockedIncrement(&g_nThreads);
  436. DbgPrint((TRC_TRACK, "[RpcSetContext(0x%x)", dwInFlags));
  437. dwErr = WZCSvcCheckRPCAccess(WZC_ACCESS_SET);
  438. if (dwErr == ERROR_SUCCESS)
  439. {
  440. dwErr = WzcContextSet(dwInFlags, pContext, pdwOutFlags);
  441. }
  442. DbgPrint((TRC_TRACK, "RpcSetContext]=%d", dwErr));
  443. BAIL_ON_WIN32_ERROR(dwErr);
  444. EnterCriticalSection(&g_wzcInternalCtxt.csContext);
  445. bLogEnabled = ((g_wzcInternalCtxt.wzcContext.dwFlags & WZC_CTXT_LOGGING_ON) != 0);
  446. LeaveCriticalSection(&g_wzcInternalCtxt.csContext);
  447. if (bLogEnabled) {
  448. if (!IsDBOpened()) {
  449. dwErr = InitWZCDbGlobals();
  450. BAIL_ON_WIN32_ERROR(dwErr);
  451. }
  452. }
  453. else {
  454. if (IsDBOpened()) {
  455. DeInitWZCDbGlobals();
  456. }
  457. }
  458. error:
  459. InterlockedDecrement(&g_nThreads);
  460. return dwErr;
  461. }
  462. extern SERVICE_STATUS g_WZCSvcStatus;
  463. DWORD
  464. RpcCmdInterface(
  465. IN DWORD dwHandle,
  466. IN DWORD dwCmdCode,
  467. IN LPWSTR wszIntfGuid,
  468. IN PRAW_DATA prdUserData)
  469. {
  470. DWORD dwErr = ERROR_SUCCESS;
  471. InterlockedIncrement(&g_nThreads);
  472. // We need to avoid processing this command if the service is not currently running
  473. // We need this protection only for this call because other than for the other calls,
  474. // RpcCmdInterface is called from 802.1x which runs within the same service. For all
  475. // the other Rpc stubs, the RPC server is shut down prior to destroying the global data
  476. // hence there is guaranteed no other calls will be made afterwards.
  477. if (g_WZCSvcStatus.dwCurrentState == SERVICE_RUNNING)
  478. {
  479. DbgPrint((TRC_TRACK, "[RpcCmdInterface(0x%x,%S)", dwCmdCode, wszIntfGuid));
  480. dwErr = WZCSvcCheckRPCAccess(WZC_ACCESS_SET);
  481. // currently this is not an RPC call! This is called directly from 802.1x. Consequently,
  482. // WZCSvcCheckRPCAccess will return RPC_S_NO_CALL_ACTIVE. We could either remove the
  483. // RPC check for now, or pass through the RPC_S_NO_CALL_ACTIVE (since later this could
  484. // become an RPC call). We do the latter!
  485. if (dwErr == ERROR_SUCCESS || dwErr == RPC_S_NO_CALL_ACTIVE)
  486. {
  487. dwErr = LstCmdInterface(dwHandle, dwCmdCode, wszIntfGuid, prdUserData);
  488. }
  489. DbgPrint((TRC_TRACK, "RpcCmdInterface]=%d", dwErr));
  490. }
  491. InterlockedDecrement(&g_nThreads);
  492. return dwErr;
  493. }
  494. VOID
  495. WZC_DBLOG_SESSION_HANDLE_rundown(
  496. WZC_DBLOG_SESSION_HANDLE hSession
  497. )
  498. {
  499. if (!g_bRpcStarted) {
  500. return;
  501. }
  502. if (!IsDBOpened()) {
  503. return;
  504. }
  505. if (hSession) {
  506. (VOID) CloseWZCDbLogSession(
  507. hSession
  508. );
  509. }
  510. return;
  511. }
  512. DWORD
  513. RpcOpenWZCDbLogSession(
  514. STRING_HANDLE pServerName,
  515. WZC_DBLOG_SESSION_HANDLE * phSession
  516. )
  517. {
  518. DWORD dwError = 0;
  519. InterlockedIncrement(&g_nThreads);
  520. dwError = WZCSvcCheckRPCAccess(WZC_ACCESS_QUERY);
  521. BAIL_ON_WIN32_ERROR(dwError);
  522. if (!IsDBOpened()) {
  523. dwError = ERROR_SERVICE_DISABLED;
  524. BAIL_ON_WIN32_ERROR(dwError);
  525. }
  526. if (!phSession) {
  527. dwError = ERROR_INVALID_PARAMETER;
  528. BAIL_ON_WIN32_ERROR(dwError);
  529. }
  530. dwError = OpenWZCDbLogSession(
  531. pServerName,
  532. 0,
  533. phSession
  534. );
  535. BAIL_ON_WIN32_ERROR(dwError);
  536. error:
  537. InterlockedDecrement(&g_nThreads);
  538. return (dwError);
  539. }
  540. DWORD
  541. RpcCloseWZCDbLogSession(
  542. WZC_DBLOG_SESSION_HANDLE * phSession
  543. )
  544. {
  545. DWORD dwError = 0;
  546. InterlockedIncrement(&g_nThreads);
  547. dwError = WZCSvcCheckRPCAccess(WZC_ACCESS_QUERY);
  548. BAIL_ON_WIN32_ERROR(dwError);
  549. if (!IsDBOpened()) {
  550. dwError = ERROR_SERVICE_DISABLED;
  551. BAIL_ON_WIN32_ERROR(dwError);
  552. }
  553. if (!phSession) {
  554. InterlockedDecrement(&g_nThreads);
  555. return (ERROR_INVALID_PARAMETER);
  556. }
  557. dwError = CloseWZCDbLogSession(
  558. *phSession
  559. );
  560. BAIL_ON_WIN32_ERROR(dwError);
  561. *phSession = NULL;
  562. error:
  563. InterlockedDecrement(&g_nThreads);
  564. return (dwError);
  565. }
  566. DWORD
  567. RpcAddWZCDbLogRecord(
  568. STRING_HANDLE pServerName,
  569. PWZC_DB_RECORD_CONTAINER pRecordContainer
  570. )
  571. {
  572. DWORD dwError = 0;
  573. PWZC_DB_RECORD pWZCRecord = NULL;
  574. InterlockedIncrement(&g_nThreads);
  575. dwError = WZCSvcCheckRPCAccess(WZC_ACCESS_SET);
  576. BAIL_ON_WIN32_ERROR(dwError);
  577. if (!IsDBOpened()) {
  578. dwError = ERROR_SERVICE_DISABLED;
  579. BAIL_ON_WIN32_ERROR(dwError);
  580. }
  581. if (!pRecordContainer) {
  582. dwError = ERROR_INVALID_PARAMETER;
  583. BAIL_ON_WIN32_ERROR(dwError);
  584. }
  585. if (!(pRecordContainer->pWZCRecords) ||
  586. !(pRecordContainer->dwNumRecords)) {
  587. dwError = ERROR_INVALID_PARAMETER;
  588. BAIL_ON_WIN32_ERROR(dwError);
  589. }
  590. pWZCRecord = pRecordContainer->pWZCRecords;
  591. dwError = AddWZCDbLogRecord(
  592. pServerName,
  593. 0,
  594. pWZCRecord,
  595. NULL
  596. );
  597. BAIL_ON_WIN32_ERROR(dwError);
  598. error:
  599. InterlockedDecrement(&g_nThreads);
  600. return (dwError);
  601. }
  602. DWORD
  603. RpcEnumWZCDbLogRecords(
  604. WZC_DBLOG_SESSION_HANDLE hSession,
  605. PWZC_DB_RECORD_CONTAINER pTemplateRecordContainer,
  606. PBOOL pbEnumFromStart,
  607. DWORD dwPreferredNumEntries,
  608. PWZC_DB_RECORD_CONTAINER * ppRecordContainer
  609. )
  610. {
  611. DWORD dwError = 0;
  612. PWZC_DB_RECORD pWZCRecords = NULL;
  613. DWORD dwNumRecords = 0;
  614. PWZC_DB_RECORD pTemplateRecord = NULL;
  615. InterlockedIncrement(&g_nThreads);
  616. dwError = WZCSvcCheckRPCAccess(WZC_ACCESS_QUERY);
  617. BAIL_ON_WIN32_ERROR(dwError);
  618. if (!IsDBOpened()) {
  619. dwError = ERROR_SERVICE_DISABLED;
  620. BAIL_ON_WIN32_ERROR(dwError);
  621. }
  622. if (!hSession || !pbEnumFromStart) {
  623. InterlockedDecrement(&g_nThreads);
  624. return (ERROR_NOT_SUPPORTED);
  625. }
  626. if (!pTemplateRecordContainer || !ppRecordContainer ||
  627. !*ppRecordContainer) {
  628. InterlockedDecrement(&g_nThreads);
  629. return (ERROR_INVALID_PARAMETER);
  630. }
  631. if (pTemplateRecordContainer->pWZCRecords) {
  632. if (pTemplateRecordContainer->dwNumRecords != 1) {
  633. InterlockedDecrement(&g_nThreads);
  634. return (ERROR_INVALID_PARAMETER);
  635. }
  636. pTemplateRecord = pTemplateRecordContainer->pWZCRecords;
  637. }
  638. dwError = EnumWZCDbLogRecordsSummary(
  639. hSession,
  640. pTemplateRecord,
  641. pbEnumFromStart,
  642. dwPreferredNumEntries,
  643. &pWZCRecords,
  644. &dwNumRecords,
  645. NULL
  646. );
  647. if (dwError != ERROR_NO_MORE_ITEMS) {
  648. BAIL_ON_WIN32_ERROR(dwError);
  649. }
  650. (*ppRecordContainer)->pWZCRecords = pWZCRecords;
  651. (*ppRecordContainer)->dwNumRecords = dwNumRecords;
  652. InterlockedDecrement(&g_nThreads);
  653. return (dwError);
  654. error:
  655. (*ppRecordContainer)->pWZCRecords = NULL;
  656. (*ppRecordContainer)->dwNumRecords = 0;
  657. InterlockedDecrement(&g_nThreads);
  658. return (dwError);
  659. }
  660. DWORD
  661. RpcFlushWZCDbLog(
  662. WZC_DBLOG_SESSION_HANDLE hSession
  663. )
  664. {
  665. DWORD dwError = 0;
  666. InterlockedIncrement(&g_nThreads);
  667. dwError = WZCSvcCheckRPCAccess(WZC_ACCESS_SET);
  668. BAIL_ON_WIN32_ERROR(dwError);
  669. if (!IsDBOpened()) {
  670. dwError = ERROR_SERVICE_DISABLED;
  671. BAIL_ON_WIN32_ERROR(dwError);
  672. }
  673. if (!hSession) {
  674. InterlockedDecrement(&g_nThreads);
  675. return (ERROR_INVALID_PARAMETER);
  676. }
  677. dwError = FlushWZCDbLog(
  678. hSession
  679. );
  680. BAIL_ON_WIN32_ERROR(dwError);
  681. error:
  682. InterlockedDecrement(&g_nThreads);
  683. return (dwError);
  684. }
  685. DWORD
  686. RpcGetWZCDbLogRecord(
  687. WZC_DBLOG_SESSION_HANDLE hSession,
  688. PWZC_DB_RECORD_CONTAINER pTemplateRecordContainer,
  689. PWZC_DB_RECORD_CONTAINER * ppRecordContainer
  690. )
  691. {
  692. DWORD dwError = 0;
  693. PWZC_DB_RECORD pWZCRecords = NULL;
  694. DWORD dwNumRecords = 0;
  695. PWZC_DB_RECORD pTemplateRecord = NULL;
  696. InterlockedIncrement(&g_nThreads);
  697. dwError = WZCSvcCheckRPCAccess(WZC_ACCESS_QUERY);
  698. BAIL_ON_WIN32_ERROR(dwError);
  699. if (!IsDBOpened()) {
  700. dwError = ERROR_SERVICE_DISABLED;
  701. BAIL_ON_WIN32_ERROR(dwError);
  702. }
  703. if (!hSession) {
  704. InterlockedDecrement(&g_nThreads);
  705. return (ERROR_NOT_SUPPORTED);
  706. }
  707. if (!pTemplateRecordContainer || !ppRecordContainer ||
  708. !*ppRecordContainer) {
  709. InterlockedDecrement(&g_nThreads);
  710. return (ERROR_INVALID_PARAMETER);
  711. }
  712. if (pTemplateRecordContainer->pWZCRecords) {
  713. if (pTemplateRecordContainer->dwNumRecords != 1) {
  714. InterlockedDecrement(&g_nThreads);
  715. return (ERROR_INVALID_PARAMETER);
  716. }
  717. pTemplateRecord = pTemplateRecordContainer->pWZCRecords;
  718. }
  719. dwError = GetWZCDbLogRecord(
  720. hSession,
  721. pTemplateRecord,
  722. &pWZCRecords,
  723. NULL
  724. );
  725. BAIL_ON_WIN32_ERROR(dwError);
  726. (*ppRecordContainer)->pWZCRecords = pWZCRecords;
  727. (*ppRecordContainer)->dwNumRecords = 1;
  728. InterlockedDecrement(&g_nThreads);
  729. return (dwError);
  730. error:
  731. (*ppRecordContainer)->pWZCRecords = NULL;
  732. (*ppRecordContainer)->dwNumRecords = 0;
  733. InterlockedDecrement(&g_nThreads);
  734. return (dwError);
  735. }