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.

8648 lines
212 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. server.cpp
  5. Abstract:
  6. Server (main) module
  7. Author:
  8. Jin Huang (jinhuang) 28-Jan-1998
  9. Revision History:
  10. --*/
  11. #include "serverp.h"
  12. #include "service.h"
  13. #include "ntrpcp.h"
  14. #include "pfp.h"
  15. #include "infp.h"
  16. #include "sceutil.h"
  17. #include "queue.h"
  18. #include <io.h>
  19. #include <lm.h>
  20. #include <lmapibuf.h>
  21. //
  22. // thread global variables
  23. //
  24. DWORD Thread gCurrentTicks=0;
  25. DWORD Thread gTotalTicks=0;
  26. BYTE Thread cbClientFlag=0;
  27. DWORD Thread gWarningCode=0;
  28. BOOL Thread gbInvalidData=FALSE;
  29. BOOL Thread bLogOn=TRUE;
  30. INT Thread gDebugLevel=-1;
  31. extern DWORD gdwMaxPDCWait;
  32. extern DWORD gdwPDCRetry;
  33. extern DWORD gdwRequirePDCSync;
  34. extern BOOL gbCheckSync;
  35. NT_PRODUCT_TYPE Thread ProductType=NtProductWinNt;
  36. PSID Thread AdminsSid=NULL;
  37. extern DWORD Thread t_pebSize;
  38. extern LPVOID Thread t_pebClient;
  39. extern LSA_HANDLE Thread LsaPrivatePolicy;
  40. extern HINSTANCE MyModuleHandle;
  41. static PPOLICY_DNS_DOMAIN_INFO DnsDomainInfo=NULL;
  42. static BOOL gbSystemShutdown=FALSE;
  43. static HANDLE hTimerQueue=NULL;
  44. //
  45. // database context list to keep tracking all client requested context
  46. // so that they can be freed properly.
  47. // if yes, we do not need to do this.
  48. //
  49. typedef struct _SCESRV_CONTEXT_LIST_ {
  50. PSCECONTEXT Context;
  51. struct _SCESRV_CONTEXT_LIST_ *Next;
  52. struct _SCESRV_CONTEXT_LIST_ *Prior;
  53. } SCESRV_CONTEXT_LIST, *PSCESRV_CONTEXT_LIST;
  54. static PSCESRV_CONTEXT_LIST pOpenContexts=NULL;
  55. static CRITICAL_SECTION ContextSync;
  56. //
  57. // database task list to control simultaneous database operations under
  58. // the same context (jet session)
  59. //
  60. typedef struct _SCESRV_DBTASK_ {
  61. PSCECONTEXT Context;
  62. CRITICAL_SECTION Sync;
  63. DWORD dInUsed;
  64. BOOL bCloseReq;
  65. struct _SCESRV_DBTASK_ *Next;
  66. struct _SCESRV_DBTASK_ *Prior;
  67. } SCESRV_DBTASK, *PSCESRV_DBTASK;
  68. static PSCESRV_DBTASK pDbTask=NULL;
  69. static CRITICAL_SECTION TaskSync;
  70. #define SCE_TASK_LOCK 0x01L
  71. #define SCE_TASK_CLOSE 0x02L
  72. //
  73. // engine task list to control simultaneous configuration/analysis engines
  74. //
  75. typedef struct _SCESRV_ENGINE_ {
  76. LPTSTR Database;
  77. struct _SCESRV_ENGINE_ *Next;
  78. struct _SCESRV_ENGINE_ *Prior;
  79. } SCESRV_ENGINE, *PSCESRV_ENGINE;
  80. static PSCESRV_ENGINE pEngines=NULL;
  81. static CRITICAL_SECTION EngSync;
  82. //
  83. // jet enigne synchronization
  84. //
  85. CRITICAL_SECTION JetSync;
  86. //
  87. // flag for stop request
  88. //
  89. static BOOL bStopRequest=FALSE;
  90. static BOOL bDbStopped=FALSE;
  91. static BOOL bEngStopped=FALSE;
  92. static CRITICAL_SECTION RpcSync;
  93. static BOOL RpcStarted = FALSE;
  94. static BOOL ServerInited = FALSE;
  95. static CRITICAL_SECTION CloseSync;
  96. static HINSTANCE hSceCliDll=NULL;
  97. static PFSCEINFWRITEINFO pfSceInfWriteInfo=NULL;
  98. static PFSCEGETINFO pfSceGetInfo=NULL;
  99. extern PSCESRV_POLQUEUE pNotificationQHead;
  100. #define SCE_POLICY_MAX_WAIT 24
  101. static DWORD gPolicyWaitCount=0;
  102. #define SERVICE_SAMSS TEXT("SamSS")
  103. SCESTATUS
  104. ScepGenerateAttachmentSections(
  105. IN PSCECONTEXT hProfile,
  106. IN SCESVC_INFO_TYPE InfoType,
  107. IN LPTSTR InfFileName,
  108. IN SCE_ATTACHMENT_TYPE aType
  109. );
  110. SCESTATUS
  111. ScepGenerateWMIAttachmentSections(
  112. IN PSCECONTEXT hProfile,
  113. IN SCESVC_INFO_TYPE InfoType,
  114. IN LPTSTR InfFileName
  115. );
  116. SCESTATUS
  117. ScepGenerateOneAttachmentSection(
  118. IN PSCECONTEXT hProfile,
  119. IN SCESVC_INFO_TYPE InfoType,
  120. IN LPTSTR InfFileName,
  121. IN LPTSTR SectionName,
  122. IN BOOL bWMISection
  123. );
  124. VOID
  125. ScepWaitForSamSS(
  126. IN PVOID pContext
  127. );
  128. SCESTATUS
  129. ScepConvertServices(
  130. IN OUT PVOID *ppServices,
  131. IN BOOL bSRForm
  132. );
  133. SCESTATUS
  134. ScepFreeConvertedServices(
  135. IN PVOID pServices,
  136. IN BOOL bSRForm
  137. );
  138. DWORD
  139. ScepConfigureConvertedFileSecurityImmediate(
  140. IN PWSTR pszDriveName
  141. );
  142. DWORD
  143. ScepWaitForSynchronizeWithPDC(
  144. IN UNICODE_STRING DnsDomainName,
  145. IN PWSTR LocalTemplateName,
  146. OUT BOOL *pbTimeout
  147. );
  148. DWORD
  149. ScepVerifyPDCRole(
  150. IN PWSTR pComputerName,
  151. OUT BOOL *pbIsPDC
  152. );
  153. ////////////////////////////////////////////////////////////////////////
  154. //
  155. // Server Control APIs
  156. //
  157. ////////////////////////////////////////////////////////////////////////
  158. VOID
  159. ScepInitServerData()
  160. /*
  161. Routine Description:
  162. Initialize global data for the server
  163. Arguments:
  164. None
  165. Return Value:
  166. None
  167. */
  168. {
  169. //
  170. // initialize RPC server controls
  171. //
  172. InitializeCriticalSection(&RpcSync);
  173. RpcStarted = FALSE;
  174. ServerInited = FALSE;
  175. //
  176. // flag to indicate if the server is requested to stop.
  177. //
  178. bStopRequest = TRUE; // will be reset when server is started up so this will
  179. // block all RPC calls before server is ready
  180. //
  181. // database operation pending tasks control
  182. //
  183. pDbTask=NULL;
  184. InitializeCriticalSection(&TaskSync);
  185. //
  186. // configuration/analysis engine task control
  187. //
  188. pEngines=NULL;
  189. InitializeCriticalSection(&EngSync);
  190. //
  191. // should also remember all created database context so that
  192. // resource can be freed when server is shutting down
  193. //
  194. InitializeCriticalSection(&CloseSync);
  195. pOpenContexts = NULL;
  196. InitializeCriticalSection(&ContextSync);
  197. bEngStopped = FALSE;
  198. bDbStopped = FALSE;
  199. //
  200. // jet engine synchronization
  201. //
  202. InitializeCriticalSection(&JetSync);
  203. //
  204. // initialize jet engine globals
  205. //
  206. SceJetInitializeData();
  207. //
  208. // initialize queue related stuff
  209. //
  210. ScepNotificationQInitialize();
  211. return;
  212. }
  213. VOID
  214. ScepUninitServerData()
  215. /*
  216. Routine Description:
  217. UnInitialize global data for the server
  218. Arguments:
  219. None
  220. Return Value:
  221. None
  222. */
  223. {
  224. //
  225. // delete the critical sections
  226. //
  227. DeleteCriticalSection(&RpcSync);
  228. DeleteCriticalSection(&TaskSync);
  229. DeleteCriticalSection(&EngSync);
  230. DeleteCriticalSection(&CloseSync);
  231. DeleteCriticalSection(&ContextSync);
  232. DeleteCriticalSection(&JetSync);
  233. return;
  234. }
  235. NTSTATUS
  236. ScepStartServerServices()
  237. /*++
  238. Routine Description:
  239. It starts the server services.
  240. Arguments:
  241. None.
  242. Return Value:
  243. NT status.
  244. --*/
  245. {
  246. NTSTATUS Status = STATUS_SUCCESS;
  247. RPC_STATUS RpcStatus;
  248. //
  249. // start RPC server
  250. //
  251. EnterCriticalSection(&RpcSync);
  252. if ( !RpcStarted ) {
  253. //
  254. // use secure RPC
  255. //
  256. Status = RpcServerRegisterAuthInfo(
  257. NULL,
  258. RPC_C_AUTHN_WINNT,
  259. NULL,
  260. NULL
  261. );
  262. if ( NT_SUCCESS(Status) ) {
  263. RpcStatus = RpcpAddInterface( L"scerpc",
  264. scerpc_ServerIfHandle);
  265. if ( RpcStatus != RPC_S_OK ) {
  266. //
  267. // can't add RPC interface
  268. //
  269. Status = I_RpcMapWin32Status(RpcStatus);
  270. } else {
  271. //
  272. // The first argument specifies the minimum number of threads to
  273. // be created to handle calls; the second argument specifies the
  274. // maximum number of concurrent calls allowed. The last argument
  275. // indicates not to wait.
  276. //
  277. RpcStatus = RpcServerListen(1,12345, 1);
  278. if ( RpcStatus == RPC_S_ALREADY_LISTENING ) {
  279. RpcStatus = RPC_S_OK;
  280. }
  281. Status = I_RpcMapWin32Status(RpcStatus);
  282. if ( RpcStatus == RPC_S_OK ) {
  283. RpcStarted = TRUE;
  284. }
  285. }
  286. }
  287. }
  288. if ( NT_SUCCESS(Status) ) {
  289. //
  290. // RPC server started
  291. // jet engine will be initialized when a database call comes in
  292. //
  293. intptr_t hFile;
  294. struct _wfinddata_t FileInfo;
  295. PWSTR szCompLog=NULL, szCompSav=NULL;
  296. SafeAllocaAllocate(szCompLog, (MAX_PATH+50)*sizeof(WCHAR));
  297. SafeAllocaAllocate(szCompSav, (MAX_PATH*2+20)*sizeof(WCHAR));
  298. //
  299. // delete the component log file
  300. //
  301. if ( szCompLog && szCompSav ) {
  302. szCompLog[0] = L'\0';
  303. GetSystemWindowsDirectory(szCompLog, MAX_PATH);
  304. szCompLog[MAX_PATH-1] = L'\0';
  305. DWORD WindirLen = wcslen(szCompLog);
  306. wcscpy(szCompSav, szCompLog);
  307. wcscat(szCompLog, L"\\security\\logs\\scecomp.log\0");
  308. wcscat(szCompSav, L"\\security\\logs\\scecomp.old\0");
  309. CopyFile(szCompLog, szCompSav, FALSE);
  310. DeleteFile(szCompLog);
  311. //
  312. // clean up temp files
  313. //
  314. wcscpy(szCompLog+WindirLen, L"\\security\\sce*.tmp");
  315. hFile = _wfindfirst(szCompLog, &FileInfo);
  316. if ( hFile != -1 ) {
  317. do {
  318. wcscpy(szCompSav+WindirLen, L"\\security\\");
  319. wcscat(szCompSav, FileInfo.name);
  320. DeleteFile(szCompSav);
  321. } while ( _wfindnext(hFile, &FileInfo) == 0 );
  322. _findclose(hFile);
  323. }
  324. //
  325. // reset the stop request flag
  326. //
  327. bEngStopped = FALSE;
  328. bDbStopped = FALSE;
  329. bStopRequest = FALSE;
  330. } else {
  331. Status = STATUS_NO_MEMORY;
  332. }
  333. SafeAllocaFree(szCompLog);
  334. SafeAllocaFree(szCompSav);
  335. }
  336. pEngines = NULL;
  337. pOpenContexts = NULL;
  338. pDbTask = NULL;
  339. //
  340. // start a system thread to handle notifications
  341. // if the thread can't be started, return failure to services.exe
  342. // which will reboot.
  343. //
  344. if ( NT_SUCCESS(Status) ) {
  345. Status = ScepQueueStartSystemThread();
  346. }
  347. LeaveCriticalSection(&RpcSync);
  348. if ( NT_SUCCESS(Status) ) {
  349. //
  350. // launch a worker thread to wait for SAMSS service
  351. // the only failure case would be out of memory, in which case,
  352. // return the error to initialize code (to shutdown the system).
  353. //
  354. Status = RtlQueueWorkItem(
  355. ScepWaitForSamSS,
  356. NULL,
  357. WT_EXECUTEONLYONCE | WT_EXECUTELONGFUNCTION
  358. ) ;
  359. }
  360. return(Status);
  361. }
  362. VOID
  363. ScepWaitForSamSS(
  364. IN PVOID pContext
  365. )
  366. {
  367. //
  368. // make sure this function handles server temination
  369. // If for some reason, the wait times out, set ServerInited to TRUE
  370. // and let RPC threads continue to perform the task (and may fail later on)
  371. //
  372. DWORD rc = ERROR_SUCCESS;
  373. SC_HANDLE ScManagerHandle = NULL;
  374. SC_HANDLE ServiceHandle = NULL;
  375. ULONG Timeout;
  376. ULONG TimeSleep;
  377. SERVICE_STATUS ServiceStatus;
  378. Timeout = 600; // 600 second timeout
  379. //
  380. // Open a handle to the Netlogon Service.
  381. //
  382. ScManagerHandle = OpenSCManager(
  383. NULL,
  384. NULL,
  385. SC_MANAGER_CONNECT );
  386. if (ScManagerHandle == NULL) {
  387. rc = ERROR_NOT_SUPPORTED;
  388. goto Cleanup;
  389. }
  390. ServiceHandle = OpenService(
  391. ScManagerHandle,
  392. SERVICE_SAMSS,
  393. SERVICE_QUERY_STATUS );
  394. if ( ServiceHandle == NULL ) {
  395. rc = ERROR_NOT_SUPPORTED;
  396. goto Cleanup;
  397. }
  398. //
  399. // Loop waiting for the SamSS service to start.
  400. //
  401. for (;;) {
  402. //
  403. // Query the status of the SamSS service.
  404. //
  405. if (! QueryServiceStatus( ServiceHandle, &ServiceStatus )) {
  406. rc = GetLastError();
  407. goto Cleanup;
  408. }
  409. //
  410. // Return or continue waiting depending on the state of
  411. // the netlogon service.
  412. //
  413. switch( ServiceStatus.dwCurrentState) {
  414. case SERVICE_RUNNING:
  415. rc = ERROR_SUCCESS;
  416. ServerInited = TRUE;
  417. goto Cleanup;
  418. case SERVICE_STOPPED:
  419. //
  420. // If Netlogon failed to start,
  421. // error out now. The caller has waited long enough to start.
  422. //
  423. if ( ServiceStatus.dwWin32ExitCode != ERROR_SERVICE_NEVER_STARTED ){
  424. rc = ERROR_NOT_SUPPORTED;
  425. goto Cleanup;
  426. }
  427. //
  428. // If SamSs has never been started on this boot,
  429. // continue waiting for it to start.
  430. //
  431. break;
  432. //
  433. // If SamSS is trying to start up now,
  434. // continue waiting for it to start.
  435. //
  436. case SERVICE_START_PENDING:
  437. break;
  438. //
  439. // Any other state is bogus.
  440. //
  441. default:
  442. rc = ERROR_NOT_SUPPORTED;
  443. goto Cleanup;
  444. }
  445. //
  446. // if server is shutting down, break this loop
  447. //
  448. if ( bStopRequest ) {
  449. break;
  450. }
  451. //
  452. // sleep for ten seconds;
  453. //
  454. if ( Timeout > 5 ) {
  455. TimeSleep = 5;
  456. } else {
  457. TimeSleep = Timeout;
  458. }
  459. Sleep(TimeSleep*1000);
  460. Timeout -= TimeSleep;
  461. if ( Timeout == 0 ) {
  462. rc = ERROR_NOT_SUPPORTED;
  463. goto Cleanup;
  464. }
  465. }
  466. ServerInited = TRUE;
  467. Cleanup:
  468. if ( ScManagerHandle != NULL ) {
  469. (VOID) CloseServiceHandle(ScManagerHandle);
  470. }
  471. if ( ServiceHandle != NULL ) {
  472. (VOID) CloseServiceHandle(ServiceHandle);
  473. }
  474. if ( ERROR_SUCCESS != rc ) {
  475. //
  476. // even if it failed to wait for SAMSS service
  477. // still set the init flag to let RPC threads go through
  478. // after sleep for the timeout
  479. //
  480. if ( Timeout > 0 ) {
  481. Sleep(Timeout*1000); // timeout second
  482. }
  483. ServerInited = TRUE;
  484. }
  485. }
  486. NTSTATUS
  487. ScepStopServerServices(
  488. IN BOOL bShutDown
  489. )
  490. /*++
  491. Routine Description:
  492. It stops the server services. This include:
  493. Blocking all new RPC requests
  494. Stop RPC server
  495. wait for all active database operations to finish
  496. Close all context handles
  497. Terminate jet engine
  498. Arguments:
  499. bShutdown - if the server is shutting down.
  500. Return Value:
  501. NT status.
  502. --*/
  503. {
  504. NTSTATUS Status=STATUS_SUCCESS;
  505. RPC_STATUS RpcStatus;
  506. LARGE_INTEGER StartTime;
  507. LARGE_INTEGER CurrentTime;
  508. DWORD dStartSeconds;
  509. DWORD dCurrentSeconds;
  510. //
  511. // no need to critical section this one because there
  512. // should be only one writer to this variable and I
  513. // don't care the readers
  514. //
  515. gbSystemShutdown = bShutDown;
  516. EnterCriticalSection(&RpcSync);
  517. //
  518. // block new RPC requests
  519. //
  520. bStopRequest = TRUE;
  521. ScepServerCancelTimer();
  522. //
  523. // stop RPC server
  524. //
  525. if ( RpcStarted ) {
  526. //
  527. // use secure RPC
  528. //
  529. RpcStatus = RpcServerUnregisterIf(scerpc_ServerIfHandle,
  530. 0,
  531. 1);
  532. if ( RpcStatus == RPC_S_OK ) {
  533. RpcStatus = RpcMgmtStopServerListening(NULL);
  534. }
  535. if ( RpcStatus == RPC_S_OK ) {
  536. RpcStatus = RpcMgmtWaitServerListen();
  537. }
  538. Status = I_RpcMapWin32Status(RpcStatus);
  539. if ( RpcStatus == RPC_S_OK ) {
  540. //
  541. // reset the flag
  542. //
  543. RpcStarted = FALSE;
  544. }
  545. }
  546. // db task
  547. EnterCriticalSection(&TaskSync);
  548. if ( pDbTask ) {
  549. bDbStopped = FALSE;
  550. LeaveCriticalSection(&TaskSync);
  551. NtQuerySystemTime(&StartTime);
  552. RtlTimeToSecondsSince1980 (&StartTime, &dStartSeconds);
  553. while ( !bDbStopped ) {
  554. //
  555. // wait until remove task routine removes everything
  556. // wait maximum 1 minutes in case some tasks are dead or looping
  557. //
  558. NtQuerySystemTime(&CurrentTime);
  559. RtlTimeToSecondsSince1980 (&CurrentTime, &dCurrentSeconds);
  560. if ( dCurrentSeconds - dStartSeconds > 60 ) {
  561. //
  562. // too long, break it
  563. //
  564. break;
  565. }
  566. }
  567. } else {
  568. //
  569. // new tasks are already blocked by bStopRequest
  570. // so pDbTask won't be !NULL again
  571. //
  572. LeaveCriticalSection(&TaskSync);
  573. }
  574. // engine task
  575. EnterCriticalSection(&EngSync);
  576. if ( pEngines ) {
  577. bEngStopped = FALSE;
  578. LeaveCriticalSection(&EngSync);
  579. NtQuerySystemTime(&StartTime);
  580. RtlTimeToSecondsSince1980 (&StartTime, &dStartSeconds);
  581. while ( !bEngStopped ) {
  582. //
  583. // wait until remove task routine removes everything
  584. // wait maximum 1 minutes in case some tasks are dead or looping
  585. //
  586. NtQuerySystemTime(&CurrentTime);
  587. RtlTimeToSecondsSince1980 (&CurrentTime, &dCurrentSeconds);
  588. if ( dCurrentSeconds - dStartSeconds > 60 ) {
  589. //
  590. // too long, break it
  591. //
  592. break;
  593. }
  594. }
  595. } else {
  596. //
  597. // new tasks are already blocked by bStopRequest
  598. // so pEngines won't be !NULL again
  599. //
  600. LeaveCriticalSection(&EngSync);
  601. }
  602. //
  603. // close all client's contexts
  604. //
  605. EnterCriticalSection(&ContextSync);
  606. PSCESRV_CONTEXT_LIST pList=pOpenContexts;
  607. PSCESRV_CONTEXT_LIST pTemp;
  608. while ( pList ) {
  609. __try {
  610. if ( pList->Context && ScepIsValidContext(pList->Context) ) {
  611. ScepCloseDatabase(pList->Context);
  612. pTemp = pList;
  613. pList = pList->Next;
  614. ScepFree(pTemp);
  615. } else {
  616. // it's already freed
  617. break;
  618. }
  619. } __except (EXCEPTION_EXECUTE_HANDLER) {
  620. break;
  621. }
  622. }
  623. pOpenContexts = NULL;
  624. LeaveCriticalSection(&ContextSync);
  625. //
  626. // check policy tasks
  627. //
  628. ScepQueuePrepareShutdown();
  629. if ( DnsDomainInfo ) {
  630. //
  631. // there is no other threads, free DnsDomainInfo
  632. //
  633. LsaFreeMemory( DnsDomainInfo );
  634. DnsDomainInfo = NULL;
  635. }
  636. //
  637. // terminate jet engine
  638. //
  639. SceJetTerminate(TRUE);
  640. SceJetDeleteJetFiles(NULL);
  641. LeaveCriticalSection(&RpcSync);
  642. return(Status);
  643. }
  644. SCESTATUS
  645. ScepRsopLog(
  646. IN AREA_INFORMATION Area,
  647. IN DWORD dwConfigStatus,
  648. IN wchar_t *pStatusInfo OPTIONAL,
  649. IN DWORD dwPrivLow OPTIONAL,
  650. IN DWORD dwPrivHigh OPTIONAL
  651. )
  652. /*
  653. Routine Description:
  654. Call back to client for logging RSOP diagnosis mode data
  655. Arguments:
  656. Area - the area being logged (used in client side in conjunction with last parameter pStatusInfo)
  657. dwConfigStatus - error/success code of the particular setting in question
  658. pStatusInfo - finer information regarding the above area (specific setting name etc.)
  659. */
  660. {
  661. //
  662. // call back to client
  663. //
  664. __try {
  665. SceClientCallbackRsopLog(Area, dwConfigStatus, pStatusInfo, dwPrivLow, dwPrivHigh);
  666. } __except(EXCEPTION_EXECUTE_HANDLER) {
  667. return(SCESTATUS_INVALID_PARAMETER);
  668. }
  669. return(SCESTATUS_SUCCESS);
  670. }
  671. SCESTATUS
  672. ScepPostProgress(
  673. IN DWORD Delta,
  674. IN AREA_INFORMATION Area,
  675. IN LPTSTR szName OPTIONAL
  676. )
  677. /*
  678. Routine Description:
  679. Call back to client for the progress of current thread, if client set
  680. the callback flag.
  681. Arguments:
  682. Delta - Ticks changes since last callback
  683. szName - the current item name
  684. */
  685. {
  686. if ( cbClientFlag ) {
  687. //
  688. // callback is requested
  689. //
  690. gCurrentTicks += Delta;
  691. //
  692. // call back to client
  693. //
  694. __try {
  695. switch (cbClientFlag ) {
  696. case SCE_CALLBACK_DELTA:
  697. SceClientCallback(Delta,0,0,(wchar_t *)szName);
  698. break;
  699. case SCE_CALLBACK_TOTAL:
  700. if ( Area ) {
  701. SceClientCallback(gCurrentTicks, gTotalTicks, Area, (wchar_t *)szName);
  702. }
  703. break;
  704. }
  705. } __except(EXCEPTION_EXECUTE_HANDLER) {
  706. return(SCESTATUS_INVALID_PARAMETER);
  707. }
  708. }
  709. return(SCESTATUS_SUCCESS);
  710. }
  711. SCESTATUS
  712. ScepValidateAndLockContext(
  713. IN PSCECONTEXT Context,
  714. IN BYTE LockFlag,
  715. IN BOOL bRequireWrite,
  716. OUT PSCESRV_DBTASK *ppTask OPTIONAL
  717. )
  718. /*
  719. Routine Description:
  720. Validate the context handle is SCE context handle.
  721. If the same context (same session) is already used for another
  722. database operation, this operation will be in waiting (a critical
  723. section pointer is returned)
  724. Arguments:
  725. Context - the context handle
  726. bLock - TRUE=perform the lock
  727. ppTask - the output task pointer
  728. Return Value:
  729. SCESTATUS
  730. */
  731. {
  732. SCESTATUS rc = SCESTATUS_INVALID_PARAMETER;
  733. if ( (LockFlag & SCE_TASK_LOCK) && !ppTask ) {
  734. //
  735. // if willing to lock, ppTask must NOT be NULL
  736. //
  737. return(rc);
  738. }
  739. if ( !Context ) {
  740. //
  741. // contents of the context will be checked within the critical section
  742. // because other threads might free the context within there.
  743. //
  744. return(rc);
  745. }
  746. if ( ppTask ) {
  747. *ppTask = NULL;
  748. }
  749. //
  750. // lock the task list and verify the context
  751. //
  752. EnterCriticalSection(&TaskSync);
  753. if ( bStopRequest ) {
  754. LeaveCriticalSection(&TaskSync);
  755. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  756. }
  757. if ( ScepIsValidContext(Context) &&
  758. ( Context->JetSessionID != JET_sesidNil ) &&
  759. ( Context->JetDbID != JET_dbidNil) ) {
  760. rc = SCESTATUS_SUCCESS;
  761. if ( bRequireWrite &&
  762. ( SCEJET_OPEN_READ_ONLY == Context->OpenFlag ) ) {
  763. //
  764. // write operation is requested but the database is only granted
  765. // read only access to this context.
  766. //
  767. rc = SCESTATUS_ACCESS_DENIED;
  768. } else {
  769. //
  770. // check if esent delay load successful
  771. //
  772. DWORD dbVersion;
  773. __try {
  774. JetGetDatabaseInfo(Context->JetSessionID,
  775. Context->JetDbID,
  776. (void *)&dbVersion,
  777. sizeof(DWORD),
  778. JET_DbInfoVersion
  779. );
  780. } __except (EXCEPTION_EXECUTE_HANDLER) {
  781. //
  782. // esent.dll is not loaded (delay) successfully
  783. //
  784. rc = SCESTATUS_MOD_NOT_FOUND;
  785. }
  786. }
  787. } else {
  788. rc = SCESTATUS_INVALID_PARAMETER;
  789. }
  790. if ( SCESTATUS_SUCCESS == rc && LockFlag ) {
  791. PSCESRV_DBTASK pdb = pDbTask;
  792. while ( pdb ) {
  793. if ( pdb->Context &&
  794. pdb->Context->JetSessionID == Context->JetSessionID &&
  795. pdb->Context->JetDbID == Context->JetDbID ) {
  796. break;
  797. }
  798. pdb = pdb->Next;
  799. }
  800. if ( pdb && pdb->Context ) {
  801. //
  802. // find the same context address and same session
  803. // critical section is in pdb->Sync
  804. //
  805. if ( pdb->bCloseReq ) {
  806. //
  807. // error this thread out because another thread is closing the
  808. // same context
  809. //
  810. rc = SCESTATUS_ACCESS_DENIED;
  811. } else if ( LockFlag & SCE_TASK_CLOSE ) {
  812. //
  813. // close on this context is requested but there are other
  814. // thread running under this context, so just turn on the flag
  815. // and the context will be closed when all pending tasks
  816. // are done
  817. //
  818. pdb->bCloseReq = TRUE;
  819. } else {
  820. //
  821. // request a lock, it's ok for this task to continue
  822. //
  823. pdb->dInUsed++;
  824. *ppTask = pdb;
  825. }
  826. } else {
  827. //
  828. // did not find the same context, this operation is ok to go
  829. // but need to add itself to the list
  830. //
  831. if ( LockFlag & SCE_TASK_CLOSE ) {
  832. //
  833. // a close context is requested, other threads using
  834. // the same context will be invalidated after this context
  835. // is freed
  836. //
  837. rc = ScepCloseDatabase(Context);
  838. } else if ( LockFlag & SCE_TASK_LOCK ) {
  839. PSCESRV_DBTASK NewDbTask = (PSCESRV_DBTASK)ScepAlloc(0, sizeof(SCESRV_DBTASK));
  840. if ( NewDbTask ) {
  841. //
  842. // new node is created
  843. //
  844. NewDbTask->Context = Context;
  845. NewDbTask->Prior = NULL;
  846. NewDbTask->dInUsed = 1;
  847. NewDbTask->bCloseReq = FALSE;
  848. InitializeCriticalSection(&(NewDbTask->Sync));
  849. //
  850. // link it to the db task list
  851. //
  852. NewDbTask->Next = pDbTask;
  853. if ( pDbTask ) {
  854. pDbTask->Prior = NewDbTask;
  855. }
  856. pDbTask = NewDbTask;
  857. *ppTask = NewDbTask;
  858. } else {
  859. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  860. }
  861. } else {
  862. //
  863. // no lock, no close, just return
  864. //
  865. }
  866. }
  867. }
  868. LeaveCriticalSection(&TaskSync);
  869. return(rc);
  870. }
  871. SCESTATUS
  872. ScepRemoveTask(
  873. PSCESRV_DBTASK pTask
  874. )
  875. /*
  876. Routine Description:
  877. Remove the task (context) from dbtask table if there is no other
  878. thread running in the same context.
  879. Arguments:
  880. pTask - the task node containing context and critical section
  881. Return Value:
  882. SCESTATUS
  883. */
  884. {
  885. if ( !pTask ) {
  886. return(SCESTATUS_SUCCESS);
  887. }
  888. SCESTATUS rc=SCESTATUS_SUCCESS;
  889. EnterCriticalSection(&TaskSync);
  890. //
  891. // find the task pointer in the task list for verification
  892. //
  893. PSCESRV_DBTASK pdb = pDbTask;
  894. while ( pdb && (ULONG_PTR)pdb != (ULONG_PTR)pTask ) {
  895. pdb = pdb->Next;
  896. }
  897. if ( pdb ) {
  898. //
  899. // find the same task node
  900. //
  901. pdb->dInUsed--;
  902. if ( 0 == pdb->dInUsed ) {
  903. //
  904. // nobody is using this task node
  905. // remove it
  906. //
  907. if ( pdb->Prior ) {
  908. pdb->Prior->Next = pdb->Next;
  909. } else {
  910. //
  911. // no parent node, set the static variable
  912. //
  913. pDbTask = pdb->Next;
  914. }
  915. //
  916. // this is a double link list, remember to remove the Prior link
  917. //
  918. if ( pdb->Next ) {
  919. pdb->Next->Prior = pdb->Prior;
  920. }
  921. //
  922. // if close request is send, close this database
  923. //
  924. if ( pdb->bCloseReq && pdb->Context ) {
  925. ScepCloseDatabase(pdb->Context);
  926. }
  927. //
  928. // delete the critical section
  929. //
  930. DeleteCriticalSection(&(pdb->Sync));
  931. //
  932. // free the memory used by this node
  933. //
  934. ScepFree(pdb);
  935. } else {
  936. //
  937. // other thread is using this task node for database operation
  938. // do nothing
  939. //
  940. }
  941. } else {
  942. //
  943. // can't find the task node in global the task list
  944. //
  945. rc = SCESTATUS_INVALID_PARAMETER;
  946. }
  947. //
  948. // if stop is requested, notify the server that db task is done
  949. //
  950. if ( bStopRequest && !pDbTask ) {
  951. bDbStopped = TRUE;
  952. }
  953. LeaveCriticalSection(&TaskSync);
  954. return(rc);
  955. }
  956. SCESTATUS
  957. ScepLockEngine(
  958. IN LPTSTR DatabaseName
  959. )
  960. /*
  961. Routine Description:
  962. Lock the database for configuration/analysis.
  963. Only one engine can run on the same database for configuration or
  964. analysis because first it's meaningless to have multiple engines
  965. running toward the same system, and second, the database is changed
  966. by the engine (table may be deleted, so on...)
  967. OpenDatabase is not locked by this lock, because each OpenDatabase
  968. has its own session and cursor and no operations such as delete the
  969. database or delete a table can be done with that context.
  970. Arguments:
  971. DefProfile - the database name
  972. Return Value:
  973. SCESTATUS
  974. */
  975. {
  976. SCESTATUS rc;
  977. if ( !DatabaseName ) {
  978. //
  979. // if willing to lock, ppTask must NOT be NULL
  980. //
  981. return(SCESTATUS_INVALID_PARAMETER);
  982. }
  983. EnterCriticalSection(&EngSync);
  984. if ( bStopRequest ) {
  985. LeaveCriticalSection(&EngSync);
  986. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  987. }
  988. PSCESRV_ENGINE pe = pEngines;
  989. while ( pe ) {
  990. if ( pe->Database &&
  991. 0 == _wcsicmp(pe->Database, DatabaseName) ) {
  992. break;
  993. }
  994. pe = pe->Next;
  995. }
  996. if ( pe ) {
  997. //
  998. // find the same database running by other threads
  999. //
  1000. rc = SCESTATUS_ALREADY_RUNNING;
  1001. } else {
  1002. //
  1003. // did not find the same database, this operation is ok to go
  1004. // but need to add itself to the list
  1005. //
  1006. PSCESRV_ENGINE NewEng = (PSCESRV_ENGINE)ScepAlloc(0, sizeof(SCESRV_ENGINE));
  1007. if ( NewEng ) {
  1008. //
  1009. // new node is created
  1010. //
  1011. NewEng->Database = (LPTSTR)ScepAlloc(LPTR, (wcslen(DatabaseName)+1)*sizeof(TCHAR));
  1012. if ( NewEng->Database ) {
  1013. wcscpy(NewEng->Database, DatabaseName);
  1014. NewEng->Next = pEngines;
  1015. NewEng->Prior = NULL;
  1016. if ( pEngines ) {
  1017. pEngines->Prior = NewEng;
  1018. }
  1019. pEngines = NewEng;
  1020. rc = SCESTATUS_SUCCESS;
  1021. } else {
  1022. ScepFree(NewEng);
  1023. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1024. }
  1025. } else {
  1026. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1027. }
  1028. }
  1029. LeaveCriticalSection(&EngSync);
  1030. return(rc);
  1031. }
  1032. SCESTATUS
  1033. ScepUnlockEngine(
  1034. IN LPTSTR DatabaseName
  1035. )
  1036. /*
  1037. Routine Description:
  1038. Unlock the database.
  1039. Arguments:
  1040. DatabaseName - the database name
  1041. Return Value:
  1042. SCESTATUS
  1043. */
  1044. {
  1045. if ( !DatabaseName ) {
  1046. //
  1047. // if no database name, just return
  1048. //
  1049. return(SCESTATUS_SUCCESS);
  1050. }
  1051. EnterCriticalSection(&EngSync);
  1052. PSCESRV_ENGINE pe = pEngines;
  1053. while ( pe && pe->Database &&
  1054. 0 != _wcsicmp(pe->Database, DatabaseName) ) {
  1055. pe = pe->Next;
  1056. }
  1057. if ( pe ) {
  1058. //
  1059. // find the database, unlock it.
  1060. //
  1061. if ( pe->Prior ) {
  1062. pe->Prior->Next = pe->Next;
  1063. } else {
  1064. //
  1065. // no parent node, set the static variable
  1066. //
  1067. pEngines = pe->Next;
  1068. }
  1069. //
  1070. // this is a double link list, remember to remove the Prior link
  1071. //
  1072. if ( pe->Next ) {
  1073. pe->Next->Prior = pe->Prior;
  1074. }
  1075. //
  1076. // free the node
  1077. //
  1078. if ( pe->Database ) {
  1079. ScepFree(pe->Database);
  1080. }
  1081. ScepFree(pe);
  1082. }
  1083. //
  1084. // if stop is requested, notify the server that engine are done
  1085. //
  1086. if ( bStopRequest && !pEngines ) {
  1087. bEngStopped = TRUE;
  1088. }
  1089. LeaveCriticalSection(&EngSync);
  1090. return(SCESTATUS_SUCCESS);
  1091. }
  1092. SCESTATUS
  1093. ScepAddToOpenContext(
  1094. IN PSCECONTEXT Context
  1095. )
  1096. {
  1097. if ( !Context ) {
  1098. return(SCESTATUS_INVALID_PARAMETER);
  1099. }
  1100. SCESTATUS rc=SCESTATUS_SUCCESS;
  1101. __try {
  1102. if ( ScepIsValidContext(Context) ) {
  1103. PSCESRV_CONTEXT_LIST pList=pOpenContexts;
  1104. //
  1105. // note, ContextSync is already entered before this function is called
  1106. //
  1107. while ( pList ) {
  1108. if ( pList->Context &&
  1109. pList->Context->JetSessionID == Context->JetSessionID &&
  1110. pList->Context->JetDbID == Context->JetDbID ) {
  1111. // 0 == memcmp(pList->Context, Context, sizeof(SCECONTEXT)) ) {
  1112. break;
  1113. }
  1114. pList = pList->Next;
  1115. }
  1116. if ( !pList ) {
  1117. //
  1118. // did not find this open context, add it
  1119. //
  1120. pList = (PSCESRV_CONTEXT_LIST)ScepAlloc(0, sizeof(SCESRV_CONTEXT_LIST));
  1121. if ( pList ) {
  1122. pList->Context = Context;
  1123. pList->Prior = NULL;
  1124. pList->Next = pOpenContexts;
  1125. if ( pOpenContexts ) {
  1126. pOpenContexts->Prior = pList;
  1127. }
  1128. pOpenContexts = pList;
  1129. } else {
  1130. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1131. }
  1132. }
  1133. } else {
  1134. rc = SCESTATUS_INVALID_PARAMETER;
  1135. }
  1136. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1137. rc = SCESTATUS_INVALID_PARAMETER;
  1138. }
  1139. return(rc);
  1140. }
  1141. BOOL
  1142. ScepNoActiveContexts()
  1143. {
  1144. BOOL bExist=FALSE;
  1145. //
  1146. // any active task ?
  1147. //
  1148. EnterCriticalSection(&TaskSync);
  1149. if ( pDbTask ) {
  1150. bExist = TRUE;
  1151. }
  1152. LeaveCriticalSection(&TaskSync);
  1153. if ( bExist ) {
  1154. return FALSE;
  1155. }
  1156. //
  1157. // any active db engine task ?
  1158. //
  1159. EnterCriticalSection(&EngSync);
  1160. if ( pEngines ) {
  1161. bExist = TRUE;
  1162. }
  1163. LeaveCriticalSection(&EngSync);
  1164. if ( bExist ) {
  1165. return FALSE;
  1166. }
  1167. //
  1168. // any open contexts ?
  1169. //
  1170. EnterCriticalSection(&ContextSync);
  1171. if ( pOpenContexts ) {
  1172. bExist = TRUE;
  1173. }
  1174. LeaveCriticalSection(&ContextSync);
  1175. return !bExist;
  1176. }
  1177. VOID
  1178. pDelayShutdownFunc(
  1179. IN PVOID Context,
  1180. IN UCHAR Timeout
  1181. )
  1182. {
  1183. if ( TryEnterCriticalSection(&JetSync) ) {
  1184. if ( hTimerQueue ) {
  1185. //
  1186. // it's necessary to do this check because there might be another thread
  1187. // cancelled this timer (after it's fired)
  1188. //
  1189. if ( ScepNoActiveContexts() ) {
  1190. SceJetTerminateNoCritical(TRUE); // clean version store (FALSE);
  1191. }
  1192. //
  1193. // 4. Note that UNLIKE before, EVERY timer needs to be deleted by calling
  1194. // RtlDeleteTimer even if they are one shot objects and have fired.
  1195. //
  1196. DeleteTimerQueueTimer( NULL, hTimerQueue, NULL );
  1197. //
  1198. // do not call CloseHandle because the handle will be closed by the
  1199. // timer function.
  1200. hTimerQueue = NULL;
  1201. }
  1202. LeaveCriticalSection(&JetSync);
  1203. } else {
  1204. //
  1205. // there is other thread holding off this one.
  1206. // This means there is still active clients, or a new client
  1207. // coming in, just return. htimerQueue will be reset by another thread
  1208. //
  1209. }
  1210. }
  1211. BOOL
  1212. ScepIfTerminateEngine()
  1213. {
  1214. //
  1215. // if system is requesting a shutdown, don't do
  1216. // anything, because the active clients and jet engine will be shutdown
  1217. //
  1218. if ( ScepIsSystemShutDown() ) {
  1219. return TRUE;
  1220. }
  1221. if ( ScepNoActiveContexts() ) {
  1222. //
  1223. // use JetSync to control timer queue
  1224. //
  1225. EnterCriticalSection(&JetSync);
  1226. DWORD Interval = 6*60*1000 ; // 6 minutes
  1227. if ( !CreateTimerQueueTimer(
  1228. &hTimerQueue,
  1229. NULL,
  1230. pDelayShutdownFunc,
  1231. NULL,
  1232. Interval,
  1233. 0,
  1234. 0 ) ) {
  1235. hTimerQueue = NULL;
  1236. }
  1237. LeaveCriticalSection(&JetSync);
  1238. return TRUE;
  1239. } else {
  1240. return FALSE;
  1241. }
  1242. }
  1243. SCESTATUS
  1244. ScepServerCancelTimer()
  1245. {
  1246. EnterCriticalSection(&JetSync);
  1247. if (hTimerQueue ) {
  1248. DeleteTimerQueueTimer(
  1249. NULL,
  1250. hTimerQueue,
  1251. (HANDLE)-1
  1252. );
  1253. hTimerQueue = NULL;
  1254. }
  1255. LeaveCriticalSection(&JetSync);
  1256. return(SCESTATUS_SUCCESS);
  1257. }
  1258. SCESTATUS
  1259. ScepValidateAndCloseDatabase(
  1260. IN PSCECONTEXT Context
  1261. )
  1262. {
  1263. SCESTATUS rc;
  1264. EnterCriticalSection(&CloseSync);
  1265. if ( ScepIsValidContext(Context) ) {
  1266. rc = SCESTATUS_SUCCESS;
  1267. } else {
  1268. rc = SCESTATUS_INVALID_PARAMETER;
  1269. }
  1270. if ( rc != SCESTATUS_SUCCESS ) {
  1271. LeaveCriticalSection(&CloseSync);
  1272. return(rc);
  1273. }
  1274. //
  1275. // be able to access the first byte
  1276. //
  1277. EnterCriticalSection(&ContextSync);
  1278. PSCESRV_CONTEXT_LIST pList=pOpenContexts;
  1279. while ( pList && ((ULONG_PTR)(pList->Context) != (ULONG_PTR)Context ||
  1280. pList->Context->JetSessionID != Context->JetSessionID ||
  1281. pList->Context->JetDbID != Context->JetDbID) ) {
  1282. pList = pList->Next;
  1283. }
  1284. if ( pList ) {
  1285. //
  1286. // find the open context, remove it from the open context list
  1287. // NOTE: both Prior and Next should be handled
  1288. //
  1289. if ( pList->Prior ) {
  1290. pList->Prior->Next = pList->Next;
  1291. } else {
  1292. pOpenContexts = pList->Next;
  1293. }
  1294. if ( pList->Next ) {
  1295. pList->Next->Prior = pList->Prior;
  1296. }
  1297. //
  1298. // free pList, do not call CloseDatabase because it will
  1299. // be closed in the following call.
  1300. //
  1301. ScepFree(pList);
  1302. }
  1303. LeaveCriticalSection(&ContextSync);
  1304. //
  1305. // if there are other threads running using the
  1306. // same database context, the close request is
  1307. // turned on. When all threads using the context
  1308. // finish, the context is closed.
  1309. //
  1310. // this client calling close won't have to wait
  1311. // for other threads using the same context
  1312. //
  1313. rc = ScepValidateAndLockContext(
  1314. (PSCECONTEXT)Context,
  1315. SCE_TASK_CLOSE,
  1316. FALSE,
  1317. NULL);
  1318. LeaveCriticalSection(&CloseSync);
  1319. //
  1320. // start a timer queue to check to see if there is active tasks/contexts
  1321. // if not, terminate jet engine
  1322. //
  1323. ScepIfTerminateEngine();
  1324. return(rc);
  1325. }
  1326. SCEPR_STATUS
  1327. SceSvcRpcQueryInfo(
  1328. IN SCEPR_CONTEXT Context,
  1329. IN SCEPR_SVCINFO_TYPE SceSvcType,
  1330. IN wchar_t *ServiceName,
  1331. IN wchar_t *Prefix OPTIONAL,
  1332. IN BOOL bExact,
  1333. OUT PSCEPR_SVCINFO __RPC_FAR *ppvInfo,
  1334. IN OUT PSCEPR_ENUM_CONTEXT psceEnumHandle
  1335. )
  1336. /*
  1337. Routine Description:
  1338. Retrieve information for the service from the database. If there are
  1339. more than the maximum allowed records for the service, only maximum
  1340. allowed records are returned. Client must use the enumeration handle
  1341. to make next query.
  1342. If during the enumeration, another client using the same context (which
  1343. is wired but it's possible) to change the information for this service,
  1344. the first client may get incorrect information.
  1345. The recommend solution is to use another context handle when doing the
  1346. update.
  1347. Arguments:
  1348. Context - the context handle
  1349. SceSvcType - the info type requested
  1350. ServiceName - the service name for which info is requested
  1351. Prefix - optional key prefix
  1352. bExact - TRUE = exact match on key
  1353. ppvInfo - output buffer
  1354. psceEnumHandle - the enumeration handle (used for next enumeration)
  1355. Return Value:
  1356. SCEPR_STATUS
  1357. */
  1358. {
  1359. SCESTATUS rc;
  1360. BOOL bAdminSidInToken = FALSE;
  1361. UINT ClientLocalFlag = 0;
  1362. if ( !ServiceName || !ppvInfo || !psceEnumHandle ) {
  1363. return(SCESTATUS_INVALID_PARAMETER);
  1364. }
  1365. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  1366. 0 == ClientLocalFlag ){
  1367. //
  1368. // to prevent denial-of-service type attacks,
  1369. // do not allow remote RPC
  1370. //
  1371. return SCESTATUS_ACCESS_DENIED;
  1372. }
  1373. //
  1374. // impersonate the client
  1375. //
  1376. rc = RpcImpersonateClient( NULL );
  1377. if (rc != RPC_S_OK) {
  1378. return( rc );
  1379. }
  1380. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  1381. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  1382. RpcRevertToSelf();
  1383. return SCESTATUS_SPECIAL_ACCOUNT;
  1384. }
  1385. //
  1386. // validate the context handle is a SCE context
  1387. // Only one database operation per context
  1388. //
  1389. PSCESRV_DBTASK pTask=NULL;
  1390. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  1391. SCE_TASK_LOCK,
  1392. FALSE,
  1393. &pTask);
  1394. if (SCESTATUS_SUCCESS == rc ) {
  1395. //
  1396. // lock the context
  1397. //
  1398. if ( pTask ) {
  1399. EnterCriticalSection(&(pTask->Sync));
  1400. }
  1401. //
  1402. // query the information now
  1403. //
  1404. #ifdef SCE_JET_TRAN
  1405. rc = SceJetJetErrorToSceStatus(
  1406. JetSetSessionContext(
  1407. ((PSCECONTEXT)Context)->JetSessionID,
  1408. (ULONG_PTR)Context
  1409. ));
  1410. if ( SCESTATUS_SUCCESS == rc ) {
  1411. #endif
  1412. __try {
  1413. rc = SceSvcpQueryInfo(
  1414. (PSCECONTEXT)Context,
  1415. (SCESVC_INFO_TYPE)SceSvcType,
  1416. (PCWSTR)ServiceName,
  1417. (PWSTR)Prefix,
  1418. bExact,
  1419. (PVOID *)ppvInfo,
  1420. (PSCE_ENUMERATION_CONTEXT)psceEnumHandle
  1421. );
  1422. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1423. //
  1424. // free ppvInfo if it's allocated
  1425. //
  1426. SceSvcpFreeMemory(*ppvInfo);
  1427. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  1428. }
  1429. #ifdef SCE_JET_TRAN
  1430. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  1431. }
  1432. #endif
  1433. //
  1434. // unlock the context
  1435. //
  1436. if ( pTask ) {
  1437. LeaveCriticalSection(&(pTask->Sync));
  1438. }
  1439. //
  1440. // remove the context from task table
  1441. //
  1442. ScepRemoveTask(pTask);
  1443. }
  1444. RpcRevertToSelf();
  1445. return((SCEPR_STATUS)rc);
  1446. }
  1447. SCEPR_STATUS
  1448. SceSvcRpcSetInfo(
  1449. IN SCEPR_CONTEXT Context,
  1450. IN SCEPR_SVCINFO_TYPE SceSvcType,
  1451. IN wchar_t *ServiceName,
  1452. IN wchar_t *Prefix OPTIONAL,
  1453. IN BOOL bExact,
  1454. IN PSCEPR_SVCINFO pvInfo
  1455. )
  1456. /*
  1457. Routine Description:
  1458. Write information for the service to the database.
  1459. Arguments:
  1460. Context - the context handle
  1461. SceSvcType - the info type requested
  1462. ServiceName - the service name for which info is requested
  1463. Prefix - optional key prefix
  1464. bExact - TRUE = exact match on key
  1465. pvInfo - output buffer
  1466. Return Value:
  1467. SCEPR_STATUS
  1468. */
  1469. {
  1470. SCESTATUS rc;
  1471. BOOL bAdminSidInToken = FALSE;
  1472. UINT ClientLocalFlag = 0;
  1473. if ( !ServiceName || !pvInfo ) {
  1474. return(SCESTATUS_INVALID_PARAMETER);
  1475. }
  1476. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  1477. 0 == ClientLocalFlag ){
  1478. //
  1479. // to prevent denial-of-service type attacks,
  1480. // do not allow remote RPC
  1481. //
  1482. return SCESTATUS_ACCESS_DENIED;
  1483. }
  1484. //
  1485. // impersonate the client
  1486. //
  1487. rc = RpcImpersonateClient( NULL );
  1488. if (rc != RPC_S_OK) {
  1489. return( rc );
  1490. }
  1491. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  1492. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  1493. RpcRevertToSelf();
  1494. return SCESTATUS_SPECIAL_ACCOUNT;
  1495. }
  1496. //
  1497. // validate the context handle is a SCE context
  1498. // Only one database operation per context
  1499. //
  1500. PSCESRV_DBTASK pTask=NULL;
  1501. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  1502. SCE_TASK_LOCK,
  1503. TRUE,
  1504. &pTask);
  1505. if (SCESTATUS_SUCCESS == rc ) {
  1506. //
  1507. // lock the context
  1508. //
  1509. if ( pTask ) {
  1510. EnterCriticalSection(&(pTask->Sync));
  1511. }
  1512. #ifdef SCE_JET_TRAN
  1513. rc = SceJetJetErrorToSceStatus(
  1514. JetSetSessionContext(
  1515. ((PSCECONTEXT)Context)->JetSessionID,
  1516. (ULONG_PTR)Context
  1517. ));
  1518. if ( SCESTATUS_SUCCESS == rc ) {
  1519. #endif
  1520. //
  1521. // set the information now
  1522. //
  1523. __try {
  1524. rc = SceSvcpSetInfo(
  1525. (PSCECONTEXT)Context,
  1526. (SCESVC_INFO_TYPE)SceSvcType,
  1527. (LPTSTR)ServiceName,
  1528. (LPTSTR)Prefix,
  1529. bExact,
  1530. 0,
  1531. (PVOID)pvInfo
  1532. );
  1533. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1534. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  1535. }
  1536. #ifdef SCE_JET_TRAN
  1537. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  1538. }
  1539. #endif
  1540. //
  1541. // unlock the context
  1542. //
  1543. if ( pTask ) {
  1544. LeaveCriticalSection(&(pTask->Sync));
  1545. }
  1546. //
  1547. // remove the context from task table
  1548. //
  1549. ScepRemoveTask(pTask);
  1550. }
  1551. RpcRevertToSelf();
  1552. return((SCEPR_STATUS)rc);
  1553. }
  1554. DWORD
  1555. SceRpcSetupUpdateObject(
  1556. IN SCEPR_CONTEXT Context,
  1557. IN wchar_t *ObjectFullName,
  1558. IN DWORD ObjectType,
  1559. IN UINT nFlag,
  1560. IN wchar_t *SDText
  1561. )
  1562. /*
  1563. Routine Description:
  1564. Update object's security settings.
  1565. Arguments:
  1566. Context - the context handle
  1567. ObjectFullName - the object's full path name
  1568. ObjectType - the object type
  1569. nFlag - the update flag
  1570. SDText - the SDDL text for the object
  1571. Return Value:
  1572. DWORD
  1573. */
  1574. {
  1575. if ( !ObjectFullName || !SDText ) {
  1576. return(SCESTATUS_INVALID_PARAMETER);
  1577. }
  1578. DWORD rc;
  1579. UINT ClientLocalFlag = 0;
  1580. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  1581. 0 == ClientLocalFlag ){
  1582. //
  1583. // to prevent denial-of-service type attacks,
  1584. // do not allow remote RPC
  1585. //
  1586. return SCESTATUS_ACCESS_DENIED;
  1587. }
  1588. //
  1589. // impersonate the client
  1590. //
  1591. rc = RpcImpersonateClient( NULL );
  1592. if (rc != RPC_S_OK) {
  1593. return( rc );
  1594. }
  1595. BOOL bAdminSidInToken = FALSE;
  1596. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  1597. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  1598. RpcRevertToSelf();
  1599. return SCESTATUS_SPECIAL_ACCOUNT;
  1600. }
  1601. //
  1602. // validate the context handle is a SCE context
  1603. // Only one database operation per context
  1604. //
  1605. PSCESRV_DBTASK pTask=NULL;
  1606. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  1607. SCE_TASK_LOCK,
  1608. TRUE,
  1609. &pTask);
  1610. if (SCESTATUS_SUCCESS == rc ) {
  1611. //
  1612. // lock the context
  1613. //
  1614. if ( pTask ) {
  1615. EnterCriticalSection(&(pTask->Sync));
  1616. }
  1617. __try {
  1618. #ifdef SCE_JET_TRAN
  1619. rc = SceJetJetErrorToSceStatus(
  1620. JetSetSessionContext(
  1621. ((PSCECONTEXT)Context)->JetSessionID,
  1622. (ULONG_PTR)Context
  1623. ));
  1624. if ( SCESTATUS_SUCCESS == rc ) {
  1625. #endif
  1626. //
  1627. // update object, return code is DWORD
  1628. //
  1629. rc = ScepSetupUpdateObject(
  1630. (PSCECONTEXT)Context,
  1631. (LPTSTR)ObjectFullName,
  1632. (SE_OBJECT_TYPE)ObjectType,
  1633. nFlag,
  1634. (LPTSTR)SDText
  1635. );
  1636. #ifdef SCE_JET_TRAN
  1637. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  1638. }
  1639. #endif
  1640. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1641. rc = ERROR_EXCEPTION_IN_SERVICE;
  1642. }
  1643. //
  1644. // unlock the context
  1645. //
  1646. if ( pTask ) {
  1647. LeaveCriticalSection(&(pTask->Sync));
  1648. }
  1649. //
  1650. // remove the context from task table
  1651. //
  1652. ScepRemoveTask(pTask);
  1653. } else {
  1654. rc = ScepSceStatusToDosError(rc);
  1655. }
  1656. RpcRevertToSelf();
  1657. return(rc);
  1658. }
  1659. DWORD
  1660. SceRpcSetupMoveFile(
  1661. IN SCEPR_CONTEXT Context,
  1662. IN wchar_t *OldName,
  1663. IN wchar_t *NewName OPTIONAL,
  1664. IN wchar_t *SDText OPTIONAL
  1665. )
  1666. /*
  1667. Routine Description:
  1668. Rename or delete a object in the section.
  1669. Arguments:
  1670. Context - the context handle
  1671. SectionName - the object's section name
  1672. OldName - existing name
  1673. NewName - new name to rename to, if NULL, the existing object is deleted
  1674. Return Value:
  1675. DWORD
  1676. */
  1677. {
  1678. if ( !OldName ) {
  1679. return(SCESTATUS_INVALID_PARAMETER);
  1680. }
  1681. UINT ClientLocalFlag = 0;
  1682. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  1683. 0 == ClientLocalFlag ){
  1684. //
  1685. // to prevent denial-of-service type attacks,
  1686. // do not allow remote RPC
  1687. //
  1688. return SCESTATUS_ACCESS_DENIED;
  1689. }
  1690. DWORD rc;
  1691. //
  1692. // impersonate the client
  1693. //
  1694. rc = RpcImpersonateClient( NULL );
  1695. if (rc != RPC_S_OK) {
  1696. return( rc );
  1697. }
  1698. BOOL bAdminSidInToken = FALSE;
  1699. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  1700. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  1701. RpcRevertToSelf();
  1702. return SCESTATUS_SPECIAL_ACCOUNT;
  1703. }
  1704. //
  1705. // validate the context handle is a SCE context
  1706. // Only one database operation per context
  1707. //
  1708. PSCESRV_DBTASK pTask=NULL;
  1709. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  1710. SCE_TASK_LOCK,
  1711. TRUE,
  1712. &pTask);
  1713. if (SCESTATUS_SUCCESS == rc ) {
  1714. //
  1715. // lock the context
  1716. //
  1717. if ( pTask ) {
  1718. EnterCriticalSection(&(pTask->Sync));
  1719. }
  1720. __try {
  1721. #ifdef SCE_JET_TRAN
  1722. rc = SceJetJetErrorToSceStatus(
  1723. JetSetSessionContext(
  1724. ((PSCECONTEXT)Context)->JetSessionID,
  1725. (ULONG_PTR)Context
  1726. ));
  1727. if ( SCESTATUS_SUCCESS == rc ) {
  1728. #endif
  1729. //
  1730. // update object, return code is DWORD
  1731. //
  1732. rc = ScepSetupMoveFile(
  1733. (PSCECONTEXT)Context,
  1734. (LPTSTR)OldName,
  1735. (LPTSTR)NewName,
  1736. (LPTSTR)SDText
  1737. );
  1738. #ifdef SCE_JET_TRAN
  1739. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  1740. }
  1741. #endif
  1742. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1743. rc = ERROR_EXCEPTION_IN_SERVICE;
  1744. }
  1745. //
  1746. // unlock the context
  1747. //
  1748. if ( pTask ) {
  1749. LeaveCriticalSection(&(pTask->Sync));
  1750. }
  1751. //
  1752. // remove the context from task table
  1753. //
  1754. ScepRemoveTask(pTask);
  1755. } else {
  1756. rc = ScepSceStatusToDosError(rc);
  1757. }
  1758. RpcRevertToSelf();
  1759. return(rc);
  1760. }
  1761. DWORD
  1762. SceRpcGenerateTemplate(
  1763. IN handle_t binding_h,
  1764. IN wchar_t *JetDbName OPTIONAL,
  1765. IN wchar_t *LogFileName OPTIONAL,
  1766. OUT SCEPR_CONTEXT __RPC_FAR *pContext
  1767. )
  1768. /*
  1769. Routine Description:
  1770. Request a context handle to generate a template from the
  1771. database. If database name is not provided, the default database
  1772. used.
  1773. Arguments:
  1774. JetDbName - optional database name, if NULL, the default is used.
  1775. LogFileName - the log file name
  1776. pContext - the output context handle
  1777. Return Value:
  1778. DWORD
  1779. */
  1780. {
  1781. if ( !pContext ) {
  1782. return(SCESTATUS_INVALID_PARAMETER);
  1783. }
  1784. UINT ClientLocalFlag = 0;
  1785. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  1786. 0 == ClientLocalFlag ){
  1787. //
  1788. // to prevent denial-of-service type attacks,
  1789. // do not allow remote RPC
  1790. //
  1791. return SCESTATUS_ACCESS_DENIED;
  1792. }
  1793. DWORD rc;
  1794. if ( bStopRequest ) {
  1795. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  1796. }
  1797. //
  1798. // there is no need to check delay loaded DLLs since now we have a exception hander
  1799. // (defined in sources)
  1800. // initialize jet engine in system context
  1801. //
  1802. rc = ScepSceStatusToDosError( SceJetInitialize(NULL) );
  1803. if ( ERROR_SUCCESS != rc ) {
  1804. return(rc);
  1805. }
  1806. //
  1807. // impersonate the client
  1808. //
  1809. rc = RpcImpersonateClient( NULL );
  1810. if (rc != RPC_S_OK) {
  1811. *pContext = NULL;
  1812. //
  1813. // terminate jet engine if there is no other clients
  1814. //
  1815. ScepIfTerminateEngine();
  1816. return( rc );
  1817. }
  1818. BOOL bAdminSidInToken = FALSE;
  1819. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  1820. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  1821. RpcRevertToSelf();
  1822. return SCESTATUS_SPECIAL_ACCOUNT;
  1823. }
  1824. //
  1825. // get the default database name if needed
  1826. // and call open database on it.
  1827. //
  1828. // OpenDatabase is not blocked by any task.
  1829. //
  1830. EnterCriticalSection(&ContextSync);
  1831. PWSTR DefProfile=NULL;
  1832. __try {
  1833. //
  1834. // figure out the default database name
  1835. // catch exception if the input buffer are bogus
  1836. //
  1837. rc = ScepGetDefaultDatabase(
  1838. JetDbName,
  1839. 0,
  1840. LogFileName,
  1841. NULL,
  1842. &DefProfile
  1843. );
  1844. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1845. rc = ERROR_EXCEPTION_IN_SERVICE;
  1846. }
  1847. if ( NO_ERROR == rc && DefProfile ) {
  1848. //
  1849. // initialize to open the database
  1850. //
  1851. ScepLogOutput3(0,0, SCEDLL_BEGIN_INIT);
  1852. ScepLogOutput3(2,0, SCEDLL_FIND_DBLOCATION, DefProfile);
  1853. //
  1854. // open the database
  1855. //
  1856. rc = ScepOpenDatabase((PCWSTR)DefProfile,
  1857. 0, // do not require analysis info,
  1858. SCEJET_OPEN_READ_ONLY,
  1859. (PSCECONTEXT *)pContext);
  1860. rc = ScepSceStatusToDosError(rc);
  1861. if ( ERROR_SUCCESS != rc ) {
  1862. ScepLogOutput3(1, rc, SCEDLL_ERROR_OPEN, DefProfile);
  1863. }
  1864. }
  1865. if (DefProfile != NULL && DefProfile != JetDbName ) {
  1866. ScepFree( DefProfile );
  1867. }
  1868. ScepLogClose();
  1869. if ( *pContext ) {
  1870. //
  1871. // if a context is to be returned, add it to the open context list
  1872. //
  1873. ScepAddToOpenContext((PSCECONTEXT)(*pContext));
  1874. rc = ERROR_SUCCESS;
  1875. } else {
  1876. rc = ERROR_FILE_NOT_FOUND;
  1877. }
  1878. LeaveCriticalSection(&ContextSync);
  1879. RpcRevertToSelf();
  1880. if ( ERROR_SUCCESS != rc ) {
  1881. //
  1882. // terminate jet engine if no other clients
  1883. //
  1884. ScepIfTerminateEngine();
  1885. }
  1886. return(rc);
  1887. }
  1888. SCEPR_STATUS
  1889. SceRpcConfigureSystem(
  1890. IN handle_t binding_h,
  1891. IN wchar_t *InfFileName OPTIONAL,
  1892. IN wchar_t *DatabaseName OPTIONAL,
  1893. IN wchar_t *LogFileName OPTIONAL,
  1894. IN DWORD ConfigOptions,
  1895. IN AREAPR Area,
  1896. IN DWORD pebSize,
  1897. IN UCHAR *pebClient OPTIONAL,
  1898. OUT PDWORD pdWarning OPTIONAL
  1899. )
  1900. /*
  1901. Routine Description:
  1902. Configure the system using the Inf template and/or existing
  1903. database info
  1904. Arguments:
  1905. See ScepConfigureSystem
  1906. Return Value:
  1907. SCEPR_STATUS
  1908. */
  1909. {
  1910. SCESTATUS rc;
  1911. UINT ClientLocalFlag = 0;
  1912. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  1913. 0 == ClientLocalFlag ){
  1914. //
  1915. // to prevent denial-of-service type attacks,
  1916. // do not allow remote RPC
  1917. //
  1918. return SCESTATUS_ACCESS_DENIED;
  1919. }
  1920. //
  1921. // impersonate the client
  1922. //
  1923. rc = RpcImpersonateClient( NULL );
  1924. if (rc != RPC_S_OK) {
  1925. return( rc );
  1926. }
  1927. BOOL bAdminSidInToken = FALSE;
  1928. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  1929. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  1930. RpcRevertToSelf();
  1931. return SCESTATUS_SPECIAL_ACCOUNT;
  1932. }
  1933. RpcRevertToSelf();
  1934. if ( bStopRequest ) {
  1935. if ( !ServerInited ) {
  1936. //
  1937. // server is in the middle of initialization
  1938. // client calls to server too early, should wait for some time
  1939. // (maximum 3 seconds)
  1940. //
  1941. INT cnt=0;
  1942. while (cnt < 6) {
  1943. Sleep(500); // .5 second
  1944. if ( ServerInited ) {
  1945. break;
  1946. }
  1947. cnt++;
  1948. }
  1949. if ( bStopRequest ) {
  1950. //
  1951. // if it's still in stop mode, return failure
  1952. //
  1953. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  1954. }
  1955. } else {
  1956. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  1957. }
  1958. }
  1959. //
  1960. // initialize jet engine in system context
  1961. //
  1962. JET_ERR JetErr=0;
  1963. BOOL bAdminLogon=FALSE;
  1964. rc = SceJetInitialize(&JetErr);
  1965. if ( rc != SCESTATUS_SUCCESS ) {
  1966. if ( ((JetErr > JET_errUnicodeTranslationBufferTooSmall) &&
  1967. (JetErr < JET_errInvalidLoggedOperation) &&
  1968. (JetErr != JET_errLogDiskFull)) ||
  1969. (JetErr == JET_errFileNotFound) ) {
  1970. //
  1971. // something is wrong with Jet log files or with other temparary databases
  1972. // if I am in setup and using system database (admin logon) or
  1973. // am in dcpromo, delete the Jet log files and try again
  1974. //
  1975. //
  1976. // impersonate the client, return DWORD error code
  1977. //
  1978. if ( RPC_S_OK == RpcImpersonateClient( NULL ) ) {
  1979. ScepIsAdminLoggedOn(&bAdminLogon, TRUE);
  1980. RpcRevertToSelf();
  1981. if ( bAdminLogon &&
  1982. (DatabaseName == NULL || SceIsSystemDatabase(DatabaseName) )) {
  1983. //
  1984. // system database and admin logon
  1985. // delete the Jet log files now.
  1986. //
  1987. SceJetDeleteJetFiles(NULL);
  1988. //
  1989. // try to initialize again (in system context)
  1990. //
  1991. rc = SceJetInitialize(&JetErr);
  1992. }
  1993. }
  1994. }
  1995. if ( rc != SCESTATUS_SUCCESS )
  1996. return(rc);
  1997. }
  1998. //
  1999. // impersonate the client, return DWORD error code
  2000. //
  2001. rc = RpcImpersonateClient( NULL );
  2002. if (rc != RPC_S_OK) {
  2003. ScepIfTerminateEngine();
  2004. return( ScepDosErrorToSceStatus(rc) );
  2005. }
  2006. //
  2007. // get the database name
  2008. //
  2009. LPTSTR DefProfile=NULL;
  2010. __try {
  2011. //
  2012. // catch exception if the input parameters are bogus
  2013. //
  2014. rc = ScepGetDefaultDatabase(
  2015. (LPCTSTR)DatabaseName,
  2016. ConfigOptions,
  2017. (LPCTSTR)LogFileName,
  2018. &bAdminLogon,
  2019. &DefProfile
  2020. );
  2021. } __except(EXCEPTION_EXECUTE_HANDLER) {
  2022. rc = ERROR_EXCEPTION_IN_SERVICE;
  2023. }
  2024. if ( ERROR_SUCCESS == rc && DefProfile ) {
  2025. //
  2026. // validate access to the database
  2027. //
  2028. rc = ScepDatabaseAccessGranted( DefProfile,
  2029. FILE_GENERIC_READ | FILE_GENERIC_WRITE,
  2030. TRUE
  2031. );
  2032. }
  2033. rc = ScepDosErrorToSceStatus(rc);
  2034. if ( SCESTATUS_SUCCESS == rc && DefProfile ) {
  2035. //
  2036. // validate the database to see if there is any configuration/
  2037. // analysis running on other threads
  2038. //
  2039. rc = ScepLockEngine(DefProfile);
  2040. if ( SCESTATUS_ALREADY_RUNNING == rc &&
  2041. (ConfigOptions & SCE_DCPROMO_WAIT ) ) {
  2042. //
  2043. // will wait for max one minute
  2044. //
  2045. DWORD DcpromoWaitCount = 0;
  2046. while ( TRUE ) {
  2047. Sleep(5000); // 5 seconds
  2048. rc = ScepLockEngine(DefProfile);
  2049. DcpromoWaitCount++;
  2050. if ( SCESTATUS_SUCCESS == rc ||
  2051. DcpromoWaitCount >= 12 ) {
  2052. break;
  2053. }
  2054. }
  2055. }
  2056. if ( SCESTATUS_SUCCESS == rc ) {
  2057. t_pebClient = (LPVOID)pebClient;
  2058. t_pebSize = pebSize;
  2059. //
  2060. // it's ok to continue this operation
  2061. // no other threads are running configuration/analysis
  2062. // based on the same database
  2063. //
  2064. DWORD dOptions = ConfigOptions;
  2065. if ( !DatabaseName ||
  2066. ( bAdminLogon && SceIsSystemDatabase(DatabaseName)) ) {
  2067. dOptions |= SCE_SYSTEM_DB;
  2068. }
  2069. __try {
  2070. //
  2071. // catch exception if InfFileName, or pebClient/pdWarning are bogus
  2072. //
  2073. rc = ScepConfigureSystem(
  2074. (LPCTSTR)InfFileName,
  2075. DefProfile,
  2076. dOptions,
  2077. bAdminLogon,
  2078. (AREA_INFORMATION)Area,
  2079. pdWarning
  2080. );
  2081. } __except(EXCEPTION_EXECUTE_HANDLER) {
  2082. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  2083. }
  2084. //
  2085. // make sure private LSA handle is closed (to avoid deadlock)
  2086. //
  2087. if ( LsaPrivatePolicy ) {
  2088. ScepNotifyLogPolicy(0, TRUE, L"Policy Prop: Private LSA handle is to be released", 0, 0, NULL );
  2089. LsaClose(LsaPrivatePolicy);
  2090. LsaPrivatePolicy = NULL;
  2091. }
  2092. //
  2093. // unlock the engine for this database
  2094. //
  2095. ScepUnlockEngine(DefProfile);
  2096. }
  2097. }
  2098. if ( DefProfile && DefProfile != DatabaseName ) {
  2099. ScepFree(DefProfile);
  2100. }
  2101. ScepLogClose();
  2102. //
  2103. // change context back
  2104. //
  2105. RpcRevertToSelf();
  2106. //
  2107. // start a timer queue to check to see if there is active tasks/contexts
  2108. // if not, terminate jet engine
  2109. //
  2110. ScepIfTerminateEngine();
  2111. return((SCEPR_STATUS)rc);
  2112. }
  2113. SCEPR_STATUS
  2114. SceRpcGetDatabaseInfo(
  2115. IN SCEPR_CONTEXT Context,
  2116. IN SCEPR_TYPE ProfileType,
  2117. IN AREAPR Area,
  2118. OUT PSCEPR_PROFILE_INFO __RPC_FAR *ppInfoBuffer,
  2119. OUT PSCEPR_ERROR_LOG_INFO __RPC_FAR *Errlog OPTIONAL
  2120. )
  2121. /*
  2122. Routine Description:
  2123. Get information from the context database.
  2124. Arguments:
  2125. Note: the InfoBuffer will always be the output buffer. Client site will
  2126. pass in a address of NULL buffer to start with for any area information
  2127. then merge this output buffer with the one clients called in.
  2128. Have to marshlling security descriptor data to add a length in pServices
  2129. See ScepGetDatabaseInfo
  2130. Return Value:
  2131. SCEPR_STATUS
  2132. */
  2133. {
  2134. if ( !ppInfoBuffer ) {
  2135. return(SCESTATUS_INVALID_PARAMETER);
  2136. }
  2137. UINT ClientLocalFlag = 0;
  2138. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  2139. 0 == ClientLocalFlag ){
  2140. //
  2141. // to prevent denial-of-service type attacks,
  2142. // do not allow remote RPC
  2143. //
  2144. return SCESTATUS_ACCESS_DENIED;
  2145. }
  2146. SCESTATUS rc;
  2147. //
  2148. // impersonate the client
  2149. //
  2150. rc = RpcImpersonateClient( NULL );
  2151. if (rc != RPC_S_OK) {
  2152. return( ScepDosErrorToSceStatus(rc) );
  2153. }
  2154. BOOL bAdminSidInToken = FALSE;
  2155. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  2156. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  2157. RpcRevertToSelf();
  2158. return SCESTATUS_SPECIAL_ACCOUNT;
  2159. }
  2160. //
  2161. // validate the context handle is a SCE context
  2162. // Only one database operation per context
  2163. //
  2164. PSCESRV_DBTASK pTask=NULL;
  2165. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  2166. SCE_TASK_LOCK,
  2167. FALSE,
  2168. &pTask);
  2169. if (SCESTATUS_SUCCESS == rc ) {
  2170. //
  2171. // lock the context
  2172. //
  2173. if ( pTask ) {
  2174. EnterCriticalSection(&(pTask->Sync));
  2175. }
  2176. __try {
  2177. //
  2178. // catch exception if Context, ppInfoBuffer, Errlog are bogus pointers
  2179. //
  2180. #ifdef SCE_JET_TRAN
  2181. rc = SceJetJetErrorToSceStatus(
  2182. JetSetSessionContext(
  2183. ((PSCECONTEXT)Context)->JetSessionID,
  2184. (ULONG_PTR)Context
  2185. ));
  2186. if ( SCESTATUS_SUCCESS == rc ) {
  2187. #endif
  2188. //
  2189. // query the information now
  2190. //
  2191. rc = ScepGetDatabaseInfo(
  2192. (PSCECONTEXT)Context,
  2193. (SCETYPE)ProfileType,
  2194. (AREA_INFORMATION)Area,
  2195. 0,
  2196. (PSCE_PROFILE_INFO *)ppInfoBuffer,
  2197. (PSCE_ERROR_LOG_INFO *)Errlog
  2198. );
  2199. #ifdef SCE_JET_TRAN
  2200. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  2201. }
  2202. #endif
  2203. } __except(EXCEPTION_EXECUTE_HANDLER) {
  2204. //
  2205. // free ppInfoBuffer if it's allocated
  2206. //
  2207. SceFreeProfileMemory( (PSCE_PROFILE_INFO)(*ppInfoBuffer));
  2208. *ppInfoBuffer = NULL;
  2209. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  2210. }
  2211. //
  2212. // unlock the context
  2213. //
  2214. if ( pTask ) {
  2215. LeaveCriticalSection(&(pTask->Sync));
  2216. }
  2217. //
  2218. // remove the context from task table
  2219. //
  2220. ScepRemoveTask(pTask);
  2221. __try {
  2222. if ( *ppInfoBuffer && (*ppInfoBuffer)->pServices ) {
  2223. //
  2224. // marshell the SCEPR_SERVICES structure for the security
  2225. // descriptor
  2226. //
  2227. for ( PSCE_SERVICES ps=(PSCE_SERVICES)((*ppInfoBuffer)->pServices);
  2228. ps != NULL; ps = ps->Next ) {
  2229. if ( ps->General.pSecurityDescriptor ) {
  2230. //
  2231. // if there is a security descriptor, it must be self relative
  2232. // because the SD is returned from SDDL apis.
  2233. //
  2234. ULONG nLen = RtlLengthSecurityDescriptor (
  2235. ps->General.pSecurityDescriptor);
  2236. if ( nLen > 0 ) {
  2237. //
  2238. // create a wrapper node to contain the security descriptor
  2239. //
  2240. PSCEPR_SR_SECURITY_DESCRIPTOR pNewWrap;
  2241. pNewWrap = (PSCEPR_SR_SECURITY_DESCRIPTOR)ScepAlloc(0, sizeof(SCEPR_SR_SECURITY_DESCRIPTOR));
  2242. if ( pNewWrap ) {
  2243. //
  2244. // assign the wrap to the structure
  2245. //
  2246. pNewWrap->SecurityDescriptor = (UCHAR *)(ps->General.pSecurityDescriptor);
  2247. pNewWrap->Length = nLen;
  2248. ps->General.pSecurityDescriptor = (PSECURITY_DESCRIPTOR)pNewWrap;
  2249. } else {
  2250. //
  2251. // no memory is available, but still continue to parse all nodes
  2252. //
  2253. nLen = 0;
  2254. }
  2255. }
  2256. if ( nLen == 0 ) {
  2257. //
  2258. // something wrong with this security descriptor
  2259. // free the buffer
  2260. //
  2261. ScepFree(ps->General.pSecurityDescriptor);
  2262. ps->General.pSecurityDescriptor = NULL;
  2263. ps->SeInfo = 0;
  2264. }
  2265. }
  2266. }
  2267. }
  2268. } __except(EXCEPTION_EXECUTE_HANDLER) {
  2269. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  2270. }
  2271. }
  2272. RpcRevertToSelf();
  2273. return((SCEPR_STATUS)rc);
  2274. }
  2275. SCEPR_STATUS
  2276. SceRpcGetObjectChildren(
  2277. IN SCEPR_CONTEXT Context,
  2278. IN SCEPR_TYPE ProfileType,
  2279. IN AREAPR Area,
  2280. IN wchar_t *ObjectPrefix,
  2281. OUT PSCEPR_OBJECT_CHILDREN __RPC_FAR *Buffer,
  2282. OUT PSCEPR_ERROR_LOG_INFO __RPC_FAR *Errlog OPTIONAL
  2283. )
  2284. /*
  2285. Routine Description:
  2286. Get immediate children of the object from the context database
  2287. Arguments:
  2288. See ScepGetObjectChildren
  2289. Return Value:
  2290. SCEPR_STATUS
  2291. */
  2292. {
  2293. if ( !ObjectPrefix || !Buffer ) {
  2294. return(SCESTATUS_INVALID_PARAMETER);
  2295. }
  2296. UINT ClientLocalFlag = 0;
  2297. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  2298. 0 == ClientLocalFlag ){
  2299. //
  2300. // to prevent denial-of-service type attacks,
  2301. // do not allow remote RPC
  2302. //
  2303. return SCESTATUS_ACCESS_DENIED;
  2304. }
  2305. //
  2306. // prevent empty strings
  2307. //
  2308. if ( ObjectPrefix[0] == L'\0' ) {
  2309. return(SCESTATUS_INVALID_PARAMETER);
  2310. }
  2311. SCESTATUS rc;
  2312. //
  2313. // impersonate the client
  2314. //
  2315. rc = RpcImpersonateClient( NULL );
  2316. if (rc != RPC_S_OK) {
  2317. return( ScepDosErrorToSceStatus(rc) );
  2318. }
  2319. BOOL bAdminSidInToken = FALSE;
  2320. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  2321. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  2322. RpcRevertToSelf();
  2323. return SCESTATUS_SPECIAL_ACCOUNT;
  2324. }
  2325. //
  2326. // validate the context handle is a SCE context
  2327. // Only one database operation per context
  2328. //
  2329. PSCESRV_DBTASK pTask=NULL;
  2330. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  2331. SCE_TASK_LOCK,
  2332. FALSE,
  2333. &pTask);
  2334. if (SCESTATUS_SUCCESS == rc ) {
  2335. //
  2336. // lock the context
  2337. //
  2338. if ( pTask ) {
  2339. EnterCriticalSection(&(pTask->Sync));
  2340. }
  2341. __try {
  2342. #ifdef SCE_JET_TRAN
  2343. rc = SceJetJetErrorToSceStatus(
  2344. JetSetSessionContext(
  2345. ((PSCECONTEXT)Context)->JetSessionID,
  2346. (ULONG_PTR)Context
  2347. ));
  2348. if ( SCESTATUS_SUCCESS == rc ) {
  2349. #endif
  2350. //
  2351. // query the information now
  2352. //
  2353. rc = ScepGetObjectChildren(
  2354. (PSCECONTEXT)Context,
  2355. (SCETYPE)ProfileType,
  2356. (AREA_INFORMATION)Area,
  2357. (PWSTR)ObjectPrefix,
  2358. SCE_IMMEDIATE_CHILDREN,
  2359. (PVOID *)Buffer,
  2360. (PSCE_ERROR_LOG_INFO *)Errlog
  2361. );
  2362. #ifdef SCE_JET_TRAN
  2363. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  2364. }
  2365. #endif
  2366. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2367. //
  2368. // free Buffer if already allocated
  2369. //
  2370. SceFreeMemory( (PVOID)(*Buffer), SCE_STRUCT_OBJECT_CHILDREN);
  2371. *Buffer = NULL;
  2372. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  2373. }
  2374. //
  2375. // unlock the context
  2376. //
  2377. if ( pTask ) {
  2378. LeaveCriticalSection(&(pTask->Sync));
  2379. }
  2380. //
  2381. // remove the context from task table
  2382. //
  2383. ScepRemoveTask(pTask);
  2384. }
  2385. RpcRevertToSelf();
  2386. return((SCEPR_STATUS)rc);
  2387. }
  2388. SCEPR_STATUS
  2389. SceRpcOpenDatabase(
  2390. IN handle_t binding_h,
  2391. IN wchar_t *DatabaseName,
  2392. IN DWORD OpenOption,
  2393. OUT SCEPR_CONTEXT __RPC_FAR *pContext
  2394. )
  2395. /*
  2396. Routine Description:
  2397. Request a context handle for the database. If bAnalysisRequired is set
  2398. to TRUE, this routine also checks if there is analysis information
  2399. in the database and return error is no analysis info is available.
  2400. Arguments:
  2401. DatabaseName - database name
  2402. OpenOption - SCE_OPEN_OPTION_REQUIRE_ANALYSIS
  2403. require analysis information in the database
  2404. SCE_OPEN_OPTION_TATTOO
  2405. open the tattoo table instead (in system database)
  2406. pContext - the output context handle
  2407. Return Value:
  2408. SCEPR_STATUS
  2409. */
  2410. {
  2411. if ( !pContext || !DatabaseName ) {
  2412. return(SCESTATUS_INVALID_PARAMETER);
  2413. }
  2414. UINT ClientLocalFlag = 0;
  2415. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  2416. 0 == ClientLocalFlag ){
  2417. //
  2418. // to prevent denial-of-service type attacks,
  2419. // do not allow remote RPC
  2420. //
  2421. return SCESTATUS_ACCESS_DENIED;
  2422. }
  2423. if ( bStopRequest ) {
  2424. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  2425. }
  2426. SCESTATUS rc;
  2427. //
  2428. // initialize jet engine in system context
  2429. //
  2430. rc = SceJetInitialize(NULL);
  2431. if ( SCESTATUS_SUCCESS != rc ) {
  2432. return(rc);
  2433. }
  2434. //
  2435. // impersonate the client
  2436. //
  2437. rc = RpcImpersonateClient( NULL );
  2438. if (rc != RPC_S_OK) {
  2439. *pContext = NULL;
  2440. rc = ScepDosErrorToSceStatus(rc);
  2441. } else {
  2442. BOOL bAdminSidInToken = FALSE;
  2443. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  2444. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  2445. RpcRevertToSelf();
  2446. return SCESTATUS_SPECIAL_ACCOUNT;
  2447. }
  2448. //
  2449. // OpenDatabase is not blocked by any task.
  2450. //
  2451. EnterCriticalSection(&ContextSync);
  2452. __try {
  2453. rc = ScepOpenDatabase(
  2454. (PCWSTR)DatabaseName,
  2455. OpenOption,
  2456. SCEJET_OPEN_READ_WRITE,
  2457. (PSCECONTEXT *)pContext
  2458. );
  2459. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2460. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  2461. }
  2462. if ( *pContext && SCESTATUS_SUCCESS == rc ) {
  2463. //
  2464. // if a context is to be returned, add it to the open context list
  2465. //
  2466. ScepAddToOpenContext((PSCECONTEXT)(*pContext));
  2467. }
  2468. LeaveCriticalSection(&ContextSync);
  2469. RpcRevertToSelf();
  2470. }
  2471. if ( rc != SCESTATUS_SUCCESS ) {
  2472. //
  2473. // make sure jet engine is terminated if no other acitve clients
  2474. //
  2475. ScepIfTerminateEngine();
  2476. }
  2477. return(rc);
  2478. }
  2479. SCEPR_STATUS
  2480. SceRpcCloseDatabase(
  2481. IN OUT SCEPR_CONTEXT *pContext
  2482. )
  2483. /*
  2484. Routine Description:
  2485. Request to close the context. If other threads on working under the
  2486. same context, the close request is send to the task list and when
  2487. all pending tasks on the same context are done, the context is freed.
  2488. This API does not wait for the closure of the database.
  2489. Arguments:
  2490. Context - the database context
  2491. Return Value:
  2492. SCEPR_STATUS
  2493. */
  2494. {
  2495. SCESTATUS rc;
  2496. //
  2497. // impersonate the client
  2498. //
  2499. UINT ClientLocalFlag = 0;
  2500. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  2501. 0 == ClientLocalFlag ){
  2502. //
  2503. // to prevent denial-of-service type attacks,
  2504. // do not allow remote RPC
  2505. //
  2506. return SCESTATUS_ACCESS_DENIED;
  2507. }
  2508. rc = RpcImpersonateClient( NULL );
  2509. if (rc != RPC_S_OK) {
  2510. return( ScepDosErrorToSceStatus(rc) );
  2511. }
  2512. BOOL bAdminSidInToken = FALSE;
  2513. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  2514. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  2515. RpcRevertToSelf();
  2516. return SCESTATUS_SPECIAL_ACCOUNT;
  2517. }
  2518. //
  2519. // remove this from the open context too
  2520. //
  2521. if ( pContext && *pContext ) {
  2522. rc = ScepValidateAndCloseDatabase((PSCECONTEXT)(*pContext));
  2523. *pContext = NULL;
  2524. }
  2525. RpcRevertToSelf();
  2526. return((SCEPR_STATUS)rc);
  2527. }
  2528. SCEPR_STATUS
  2529. SceRpcGetDatabaseDescription(
  2530. IN SCEPR_CONTEXT Context,
  2531. OUT wchar_t __RPC_FAR **Description
  2532. )
  2533. /*
  2534. Routine Description:
  2535. Query database description from the context
  2536. Arguments:
  2537. Context - the database context
  2538. Description - the output buffer of description
  2539. Return Value:
  2540. SCEPR_STATUS
  2541. */
  2542. {
  2543. if ( !Context || !Description ) {
  2544. return(SCESTATUS_INVALID_PARAMETER);
  2545. }
  2546. UINT ClientLocalFlag = 0;
  2547. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  2548. 0 == ClientLocalFlag ){
  2549. //
  2550. // to prevent denial-of-service type attacks,
  2551. // do not allow remote RPC
  2552. //
  2553. return SCESTATUS_ACCESS_DENIED;
  2554. }
  2555. SCESTATUS rc;
  2556. //
  2557. // impersonate the client
  2558. //
  2559. rc = RpcImpersonateClient( NULL );
  2560. if (rc != RPC_S_OK) {
  2561. return( ScepDosErrorToSceStatus(rc) );
  2562. }
  2563. BOOL bAdminSidInToken = FALSE;
  2564. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  2565. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  2566. RpcRevertToSelf();
  2567. return SCESTATUS_SPECIAL_ACCOUNT;
  2568. }
  2569. //
  2570. // the context needs to be locked in case another thread
  2571. // is calling close database on it
  2572. //
  2573. PSCESRV_DBTASK pTask=NULL;
  2574. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  2575. SCE_TASK_LOCK,
  2576. FALSE,
  2577. &pTask);
  2578. if (SCESTATUS_SUCCESS == rc ) {
  2579. #ifdef SCE_JET_TRAN
  2580. rc = SceJetJetErrorToSceStatus(
  2581. JetSetSessionContext(
  2582. ((PSCECONTEXT)Context)->JetSessionID,
  2583. (ULONG_PTR)Context
  2584. ));
  2585. if ( SCESTATUS_SUCCESS == rc ) {
  2586. #endif
  2587. //
  2588. // do not need to lock the context because
  2589. // it's reading information from one record table
  2590. //
  2591. rc = SceJetGetDescription(
  2592. (PSCECONTEXT)Context,
  2593. (PWSTR *)Description
  2594. );
  2595. #ifdef SCE_JET_TRAN
  2596. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  2597. }
  2598. #endif
  2599. //
  2600. // remove the context from task table
  2601. //
  2602. ScepRemoveTask(pTask);
  2603. }
  2604. RpcRevertToSelf();
  2605. return((SCEPR_STATUS)rc);
  2606. }
  2607. SCEPR_STATUS
  2608. SceRpcGetDBTimeStamp(
  2609. IN SCEPR_CONTEXT Context,
  2610. OUT PLARGE_INTEGER ptsConfig,
  2611. OUT PLARGE_INTEGER ptsAnalysis
  2612. )
  2613. /*
  2614. Routine Description:
  2615. Query the last configuration and analysis time stamp from the context.
  2616. Arguments:
  2617. Context - the database context
  2618. ptsConfig - the last configuration time stamp
  2619. ptsAnalysis - the last analysis time stamp
  2620. Return Value:
  2621. SCEPR_STATUS
  2622. */
  2623. {
  2624. if ( !Context || !ptsConfig || !ptsAnalysis ) {
  2625. return(SCESTATUS_INVALID_PARAMETER);
  2626. }
  2627. UINT ClientLocalFlag = 0;
  2628. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  2629. 0 == ClientLocalFlag ){
  2630. //
  2631. // to prevent denial-of-service type attacks,
  2632. // do not allow remote RPC
  2633. //
  2634. return SCESTATUS_ACCESS_DENIED;
  2635. }
  2636. SCESTATUS rc;
  2637. //
  2638. // impersonate the client
  2639. //
  2640. rc = RpcImpersonateClient( NULL );
  2641. if (rc != RPC_S_OK) {
  2642. return( ScepDosErrorToSceStatus(rc) );
  2643. }
  2644. BOOL bAdminSidInToken = FALSE;
  2645. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  2646. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  2647. RpcRevertToSelf();
  2648. return SCESTATUS_SPECIAL_ACCOUNT;
  2649. }
  2650. //
  2651. // the context needs to be locked in case another thread
  2652. // is calling close database on it
  2653. //
  2654. PSCESRV_DBTASK pTask=NULL;
  2655. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  2656. SCE_TASK_LOCK,
  2657. FALSE,
  2658. &pTask);
  2659. if (SCESTATUS_SUCCESS == rc ) {
  2660. #ifdef SCE_JET_TRAN
  2661. rc = SceJetJetErrorToSceStatus(
  2662. JetSetSessionContext(
  2663. ((PSCECONTEXT)Context)->JetSessionID,
  2664. (ULONG_PTR)Context
  2665. ));
  2666. if ( SCESTATUS_SUCCESS == rc ) {
  2667. #endif
  2668. //
  2669. // do not need to lock the context because
  2670. // it's reading information from one record table
  2671. //
  2672. rc = SceJetGetTimeStamp(
  2673. (PSCECONTEXT)Context,
  2674. ptsConfig,
  2675. ptsAnalysis
  2676. );
  2677. #ifdef SCE_JET_TRAN
  2678. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  2679. }
  2680. #endif
  2681. //
  2682. // remove the context from task table
  2683. //
  2684. ScepRemoveTask(pTask);
  2685. }
  2686. RpcRevertToSelf();
  2687. return((SCEPR_STATUS)rc);
  2688. }
  2689. SCEPR_STATUS
  2690. SceRpcGetObjectSecurity(
  2691. IN SCEPR_CONTEXT Context,
  2692. IN SCEPR_TYPE DbProfileType,
  2693. IN AREAPR Area,
  2694. IN wchar_t *ObjectName,
  2695. OUT PSCEPR_OBJECT_SECURITY __RPC_FAR *ObjSecurity
  2696. )
  2697. /*
  2698. Routine Description:
  2699. Query security settings for an object from the context database.
  2700. Arguments:
  2701. Context - the database context
  2702. DbProfileType - the database table type
  2703. Area - the security area (file, registry, so on.)
  2704. ObjectName - the object's full name
  2705. ObjSecurity - object security settings structure
  2706. Return Value:
  2707. SCEPR_STATUS
  2708. */
  2709. {
  2710. if ( !Context || !ObjSecurity || !ObjectName ) {
  2711. return(SCESTATUS_INVALID_PARAMETER);
  2712. }
  2713. UINT ClientLocalFlag = 0;
  2714. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  2715. 0 == ClientLocalFlag ){
  2716. //
  2717. // to prevent denial-of-service type attacks,
  2718. // do not allow remote RPC
  2719. //
  2720. return SCESTATUS_ACCESS_DENIED;
  2721. }
  2722. SCESTATUS rc;
  2723. //
  2724. // impersonate the client
  2725. //
  2726. rc = RpcImpersonateClient( NULL );
  2727. if (rc != RPC_S_OK) {
  2728. return( ScepDosErrorToSceStatus(rc) );
  2729. }
  2730. BOOL bAdminSidInToken = FALSE;
  2731. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  2732. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  2733. RpcRevertToSelf();
  2734. return SCESTATUS_SPECIAL_ACCOUNT;
  2735. }
  2736. //
  2737. // validate the context handle is a SCE context
  2738. // Only one database operation per context
  2739. //
  2740. PSCESRV_DBTASK pTask=NULL;
  2741. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  2742. SCE_TASK_LOCK,
  2743. FALSE,
  2744. &pTask);
  2745. if (SCESTATUS_SUCCESS == rc ) {
  2746. //
  2747. // lock the context
  2748. //
  2749. if ( pTask ) {
  2750. EnterCriticalSection(&(pTask->Sync));
  2751. }
  2752. #ifdef SCE_JET_TRAN
  2753. rc = SceJetJetErrorToSceStatus(
  2754. JetSetSessionContext(
  2755. ((PSCECONTEXT)Context)->JetSessionID,
  2756. (ULONG_PTR)Context
  2757. ));
  2758. if ( SCESTATUS_SUCCESS == rc ) {
  2759. #endif
  2760. //
  2761. // query the information now
  2762. //
  2763. rc = ScepGetObjectSecurity(
  2764. (PSCECONTEXT)Context,
  2765. (SCETYPE)DbProfileType,
  2766. (AREA_INFORMATION)Area,
  2767. (PWSTR)ObjectName,
  2768. (PSCE_OBJECT_SECURITY *)ObjSecurity
  2769. );
  2770. #ifdef SCE_JET_TRAN
  2771. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  2772. }
  2773. #endif
  2774. //
  2775. // unlock the context
  2776. //
  2777. if ( pTask ) {
  2778. LeaveCriticalSection(&(pTask->Sync));
  2779. }
  2780. //
  2781. // remove the context from task table
  2782. //
  2783. ScepRemoveTask(pTask);
  2784. //
  2785. // convert the security descriptor
  2786. //
  2787. if ( ( SCESTATUS_SUCCESS == rc ) &&
  2788. *ObjSecurity &&
  2789. (*ObjSecurity)->pSecurityDescriptor ) {
  2790. //
  2791. // there is a security descriptor, it must be self relative
  2792. // because it's returned from the SDDL api.
  2793. //
  2794. ULONG nLen = RtlLengthSecurityDescriptor (
  2795. (PSECURITY_DESCRIPTOR)((*ObjSecurity)->pSecurityDescriptor));
  2796. if ( nLen > 0 ) {
  2797. //
  2798. // create a wrapper node to contain the security descriptor
  2799. //
  2800. PSCEPR_SR_SECURITY_DESCRIPTOR pNewWrap;
  2801. pNewWrap = (PSCEPR_SR_SECURITY_DESCRIPTOR)ScepAlloc(0, sizeof(SCEPR_SR_SECURITY_DESCRIPTOR));
  2802. if ( pNewWrap ) {
  2803. //
  2804. // assign the wrap to the structure
  2805. //
  2806. pNewWrap->SecurityDescriptor = (UCHAR *)((*ObjSecurity)->pSecurityDescriptor);
  2807. pNewWrap->Length = nLen;
  2808. (*ObjSecurity)->pSecurityDescriptor = (SCEPR_SR_SECURITY_DESCRIPTOR *)pNewWrap;
  2809. } else {
  2810. //
  2811. // no memory is available, but still continue to parse all nodes
  2812. //
  2813. nLen = 0;
  2814. }
  2815. }
  2816. if ( nLen == 0 ) {
  2817. //
  2818. // something wrong with this security descriptor
  2819. // free the buffer
  2820. //
  2821. ScepFree((*ObjSecurity)->pSecurityDescriptor);
  2822. (*ObjSecurity)->pSecurityDescriptor = NULL;
  2823. (*ObjSecurity)->SeInfo = 0;
  2824. }
  2825. }
  2826. }
  2827. RpcRevertToSelf();
  2828. return((SCEPR_STATUS)rc);
  2829. }
  2830. SCEPR_STATUS
  2831. SceRpcGetAnalysisSummary(
  2832. IN SCEPR_CONTEXT Context,
  2833. IN AREAPR Area,
  2834. OUT PDWORD pCount
  2835. )
  2836. /*
  2837. Routine Description:
  2838. Query security settings for an object from the context database.
  2839. Arguments:
  2840. Context - the database context
  2841. Area - the security area (file, registry, so on.)
  2842. pCount - the output count
  2843. Return Value:
  2844. SCEPR_STATUS
  2845. */
  2846. {
  2847. if ( !Context || !pCount ) {
  2848. return(SCESTATUS_INVALID_PARAMETER);
  2849. }
  2850. UINT ClientLocalFlag = 0;
  2851. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  2852. 0 == ClientLocalFlag ){
  2853. //
  2854. // to prevent denial-of-service type attacks,
  2855. // do not allow remote RPC
  2856. //
  2857. return SCESTATUS_ACCESS_DENIED;
  2858. }
  2859. SCESTATUS rc;
  2860. //
  2861. // impersonate the client
  2862. //
  2863. rc = RpcImpersonateClient( NULL );
  2864. if (rc != RPC_S_OK) {
  2865. return( ScepDosErrorToSceStatus(rc) );
  2866. }
  2867. BOOL bAdminSidInToken = FALSE;
  2868. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  2869. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  2870. RpcRevertToSelf();
  2871. return SCESTATUS_SPECIAL_ACCOUNT;
  2872. }
  2873. //
  2874. // validate the context handle is a SCE context
  2875. // Only one database operation per context
  2876. //
  2877. PSCESRV_DBTASK pTask=NULL;
  2878. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  2879. SCE_TASK_LOCK,
  2880. FALSE,
  2881. &pTask);
  2882. if (SCESTATUS_SUCCESS == rc ) {
  2883. //
  2884. // lock the context
  2885. //
  2886. if ( pTask ) {
  2887. EnterCriticalSection(&(pTask->Sync));
  2888. }
  2889. #ifdef SCE_JET_TRAN
  2890. rc = SceJetJetErrorToSceStatus(
  2891. JetSetSessionContext(
  2892. ((PSCECONTEXT)Context)->JetSessionID,
  2893. (ULONG_PTR)Context
  2894. ));
  2895. if ( SCESTATUS_SUCCESS == rc ) {
  2896. #endif
  2897. //
  2898. // query the information now
  2899. //
  2900. rc = ScepGetAnalysisSummary(
  2901. (PSCECONTEXT)Context,
  2902. (AREA_INFORMATION)Area,
  2903. pCount
  2904. );
  2905. #ifdef SCE_JET_TRAN
  2906. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  2907. }
  2908. #endif
  2909. //
  2910. // unlock the context
  2911. //
  2912. if ( pTask ) {
  2913. LeaveCriticalSection(&(pTask->Sync));
  2914. }
  2915. //
  2916. // remove the context from task table
  2917. //
  2918. ScepRemoveTask(pTask);
  2919. }
  2920. RpcRevertToSelf();
  2921. return((SCEPR_STATUS)rc);
  2922. }
  2923. SCEPR_STATUS
  2924. SceRpcAnalyzeSystem(
  2925. IN handle_t binding_h,
  2926. IN wchar_t *InfFileName OPTIONAL,
  2927. IN wchar_t *DatabaseName OPTIONAL,
  2928. IN wchar_t *LogFileName OPTIONAL,
  2929. IN AREAPR Area,
  2930. IN DWORD AnalyzeOptions,
  2931. IN DWORD pebSize,
  2932. IN UCHAR *pebClient OPTIONAL,
  2933. OUT PDWORD pdWarning OPTIONAL
  2934. )
  2935. /*
  2936. Routine Description:
  2937. Analyze the system using the Inf template and/or existing
  2938. database info
  2939. Arguments:
  2940. See ScepAnalyzeSystem
  2941. Return Value:
  2942. SCEPR_STATUS
  2943. */
  2944. {
  2945. SCESTATUS rc;
  2946. if ( bStopRequest ) {
  2947. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  2948. }
  2949. UINT ClientLocalFlag = 0;
  2950. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  2951. 0 == ClientLocalFlag ){
  2952. //
  2953. // to prevent denial-of-service type attacks,
  2954. // do not allow remote RPC
  2955. //
  2956. return SCESTATUS_ACCESS_DENIED;
  2957. }
  2958. //
  2959. // initialize jet engine in system context
  2960. //
  2961. rc = SceJetInitialize(NULL);
  2962. if ( rc != SCESTATUS_SUCCESS ) {
  2963. return(rc);
  2964. }
  2965. //
  2966. // impersonate the client, return DWORD error code
  2967. //
  2968. rc = RpcImpersonateClient( NULL );
  2969. if (rc != RPC_S_OK) {
  2970. ScepIfTerminateEngine();
  2971. return( ScepDosErrorToSceStatus(rc) );
  2972. }
  2973. BOOL bAdminSidInToken = FALSE;
  2974. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  2975. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  2976. RpcRevertToSelf();
  2977. return SCESTATUS_SPECIAL_ACCOUNT;
  2978. }
  2979. //
  2980. // get the database name
  2981. //
  2982. BOOL bAdminLogon=FALSE;
  2983. LPTSTR DefProfile=NULL;
  2984. __try {
  2985. rc = ScepGetDefaultDatabase(
  2986. (AnalyzeOptions & SCE_GENERATE_ROLLBACK) ? NULL : (LPCTSTR)DatabaseName,
  2987. AnalyzeOptions,
  2988. (LPCTSTR)LogFileName,
  2989. &bAdminLogon,
  2990. &DefProfile
  2991. );
  2992. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2993. rc = ERROR_EXCEPTION_IN_SERVICE;
  2994. }
  2995. if ( (AnalyzeOptions & SCE_GENERATE_ROLLBACK)
  2996. && !bAdminLogon ) {
  2997. //
  2998. // only allow admin to use system database to generate rollback
  2999. // is this the correct design?
  3000. //
  3001. rc = ERROR_ACCESS_DENIED;
  3002. }
  3003. if ( ERROR_SUCCESS == rc && DefProfile ) {
  3004. //
  3005. // validate access to the database
  3006. //
  3007. rc = ScepDatabaseAccessGranted( DefProfile,
  3008. FILE_GENERIC_READ | FILE_GENERIC_WRITE,
  3009. TRUE
  3010. );
  3011. }
  3012. rc = ScepDosErrorToSceStatus(rc);
  3013. if ( SCESTATUS_SUCCESS == rc && DefProfile ) {
  3014. //
  3015. // validate the database to see if there is any configuration/
  3016. // analysis running on other threads
  3017. //
  3018. rc = ScepLockEngine(DefProfile);
  3019. if ( SCESTATUS_SUCCESS == rc ) {
  3020. t_pebClient = (LPVOID)pebClient;
  3021. t_pebSize = pebSize;
  3022. //
  3023. // it's ok to continue this operation
  3024. // no other threads are running configuration/analysis
  3025. // based on the same database
  3026. //
  3027. DWORD dOptions = AnalyzeOptions;
  3028. if ( !(AnalyzeOptions & SCE_GENERATE_ROLLBACK) ) {
  3029. if ( !DatabaseName ||
  3030. ( bAdminLogon && SceIsSystemDatabase(DatabaseName)) ) {
  3031. dOptions |= SCE_SYSTEM_DB;
  3032. }
  3033. }
  3034. __try {
  3035. rc = ScepAnalyzeSystem(
  3036. (LPCTSTR)InfFileName,
  3037. DefProfile,
  3038. dOptions,
  3039. bAdminLogon,
  3040. (AREA_INFORMATION)Area,
  3041. pdWarning,
  3042. (AnalyzeOptions & SCE_GENERATE_ROLLBACK) ? DatabaseName : NULL
  3043. );
  3044. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3045. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  3046. }
  3047. //
  3048. // unlock the engine for this database
  3049. //
  3050. ScepUnlockEngine(DefProfile);
  3051. }
  3052. }
  3053. if ( DefProfile && DefProfile != DatabaseName ) {
  3054. ScepFree(DefProfile);
  3055. }
  3056. ScepLogClose();
  3057. //
  3058. // change context back
  3059. //
  3060. RpcRevertToSelf();
  3061. //
  3062. // start a timer queue to check to see if there is active tasks/contexts
  3063. // if not, terminate jet engine
  3064. //
  3065. ScepIfTerminateEngine();
  3066. return((SCEPR_STATUS)rc);
  3067. }
  3068. SCEPR_STATUS
  3069. SceRpcUpdateDatabaseInfo(
  3070. IN SCEPR_CONTEXT Context,
  3071. IN SCEPR_TYPE ProfileType,
  3072. IN AREAPR Area,
  3073. IN PSCEPR_PROFILE_INFO pInfo,
  3074. IN DWORD dwMode
  3075. )
  3076. /*
  3077. Routine Description:
  3078. Update database in the context using pInfo
  3079. Arguments:
  3080. Context - the database context
  3081. ProfileType - the database table type
  3082. Area - the security area (security policy... except objects's area)
  3083. pInfo - the info to update
  3084. Return Value:
  3085. SCEPR_STATUS
  3086. */
  3087. {
  3088. if ( !Context || !pInfo ) {
  3089. return(SCESTATUS_INVALID_PARAMETER);
  3090. }
  3091. UINT ClientLocalFlag = 0;
  3092. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  3093. 0 == ClientLocalFlag ){
  3094. //
  3095. // to prevent denial-of-service type attacks,
  3096. // do not allow remote RPC
  3097. //
  3098. return SCESTATUS_ACCESS_DENIED;
  3099. }
  3100. SCESTATUS rc;
  3101. //
  3102. // impersonate the client
  3103. //
  3104. rc = RpcImpersonateClient( NULL );
  3105. if (rc != RPC_S_OK) {
  3106. return( ScepDosErrorToSceStatus(rc) );
  3107. }
  3108. BOOL bAdminSidInToken = FALSE;
  3109. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  3110. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  3111. RpcRevertToSelf();
  3112. return SCESTATUS_SPECIAL_ACCOUNT;
  3113. }
  3114. //
  3115. // validate the context handle is a SCE context
  3116. // Only one database operation per context
  3117. //
  3118. PSCESRV_DBTASK pTask=NULL;
  3119. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  3120. SCE_TASK_LOCK,
  3121. TRUE,
  3122. &pTask);
  3123. if (SCESTATUS_SUCCESS == rc ) {
  3124. PSCEPR_SERVICES pOldServices = pInfo->pServices;
  3125. //
  3126. // Convert SCEPR_PROFILE_INFO into SCE_PROFILE_INFO
  3127. //
  3128. if ( (Area & AREA_SYSTEM_SERVICE) &&
  3129. pOldServices ) {
  3130. rc = ScepConvertServices( (PVOID *)&(pInfo->pServices), TRUE );
  3131. } else {
  3132. pInfo->pServices = NULL;
  3133. }
  3134. if ( SCESTATUS_SUCCESS == rc ) {
  3135. //
  3136. // lock the context
  3137. //
  3138. if ( pTask ) {
  3139. EnterCriticalSection(&(pTask->Sync));
  3140. }
  3141. __try {
  3142. #ifdef SCE_JET_TRAN
  3143. rc = SceJetJetErrorToSceStatus(
  3144. JetSetSessionContext(
  3145. ((PSCECONTEXT)Context)->JetSessionID,
  3146. (ULONG_PTR)Context
  3147. ));
  3148. if ( SCESTATUS_SUCCESS == rc ) {
  3149. #endif
  3150. //
  3151. // update the information now
  3152. //
  3153. if ( dwMode & SCE_UPDATE_LOCAL_POLICY ) {
  3154. //
  3155. // update local policy only
  3156. //
  3157. rc = ScepUpdateLocalTable(
  3158. (PSCECONTEXT)Context,
  3159. (AREA_INFORMATION)Area,
  3160. (PSCE_PROFILE_INFO)pInfo,
  3161. dwMode
  3162. );
  3163. } else {
  3164. //
  3165. // update the database (SMP and SAP)
  3166. //
  3167. rc = ScepUpdateDatabaseInfo(
  3168. (PSCECONTEXT)Context,
  3169. (AREA_INFORMATION)Area,
  3170. (PSCE_PROFILE_INFO)pInfo
  3171. );
  3172. }
  3173. #ifdef SCE_JET_TRAN
  3174. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  3175. }
  3176. #endif
  3177. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3178. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  3179. }
  3180. //
  3181. // unlock the context
  3182. //
  3183. if ( pTask ) {
  3184. LeaveCriticalSection(&(pTask->Sync));
  3185. }
  3186. ScepFreeConvertedServices( pInfo->pServices, FALSE );
  3187. }
  3188. pInfo->pServices = pOldServices;
  3189. //
  3190. // remove the context from task table
  3191. //
  3192. ScepRemoveTask(pTask);
  3193. }
  3194. RpcRevertToSelf();
  3195. return((SCEPR_STATUS)rc);
  3196. }
  3197. SCEPR_STATUS
  3198. SceRpcUpdateObjectInfo(
  3199. IN SCEPR_CONTEXT Context,
  3200. IN AREAPR Area,
  3201. IN wchar_t *ObjectName,
  3202. IN DWORD NameLen,
  3203. IN BYTE ConfigStatus,
  3204. IN BOOL IsContainer,
  3205. IN SCEPR_SR_SECURITY_DESCRIPTOR *pSD OPTIONAL,
  3206. IN SECURITY_INFORMATION SeInfo,
  3207. OUT PBYTE pAnalysisStatus
  3208. )
  3209. /*
  3210. Routine Description:
  3211. Update object's security settings in the database.
  3212. Arguments:
  3213. See ScepUpdateObjectInfo
  3214. Return Value:
  3215. SCEPR_STATUS
  3216. */
  3217. {
  3218. if ( !Context || !ObjectName ) {
  3219. return(SCESTATUS_INVALID_PARAMETER);
  3220. }
  3221. SCESTATUS rc;
  3222. UINT ClientLocalFlag = 0;
  3223. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  3224. 0 == ClientLocalFlag ){
  3225. //
  3226. // to prevent denial-of-service type attacks,
  3227. // do not allow remote RPC
  3228. //
  3229. return SCESTATUS_ACCESS_DENIED;
  3230. }
  3231. //
  3232. // impersonate the client
  3233. //
  3234. rc = RpcImpersonateClient( NULL );
  3235. if (rc != RPC_S_OK) {
  3236. return( ScepDosErrorToSceStatus(rc) );
  3237. }
  3238. BOOL bAdminSidInToken = FALSE;
  3239. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  3240. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  3241. RpcRevertToSelf();
  3242. return SCESTATUS_SPECIAL_ACCOUNT;
  3243. }
  3244. //
  3245. // validate the context handle is a SCE context
  3246. // Only one database operation per context
  3247. //
  3248. PSCESRV_DBTASK pTask=NULL;
  3249. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  3250. SCE_TASK_LOCK,
  3251. TRUE,
  3252. &pTask);
  3253. if (SCESTATUS_SUCCESS == rc ) {
  3254. //
  3255. // lock the context
  3256. //
  3257. if ( pTask ) {
  3258. EnterCriticalSection(&(pTask->Sync));
  3259. }
  3260. #ifdef SCE_JET_TRAN
  3261. rc = SceJetJetErrorToSceStatus(
  3262. JetSetSessionContext(
  3263. ((PSCECONTEXT)Context)->JetSessionID,
  3264. (ULONG_PTR)Context
  3265. ));
  3266. if ( SCESTATUS_SUCCESS == rc ) {
  3267. #endif
  3268. //
  3269. // update the object info now
  3270. //
  3271. __try {
  3272. rc = ScepUpdateObjectInfo(
  3273. (PSCECONTEXT)Context,
  3274. (AREA_INFORMATION)Area,
  3275. (PWSTR)ObjectName,
  3276. NameLen,
  3277. ConfigStatus,
  3278. IsContainer,
  3279. pSD ? (PSECURITY_DESCRIPTOR)(pSD->SecurityDescriptor) : NULL,
  3280. SeInfo,
  3281. pAnalysisStatus
  3282. );
  3283. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3284. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  3285. }
  3286. #ifdef SCE_JET_TRAN
  3287. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  3288. }
  3289. #endif
  3290. //
  3291. // unlock the context
  3292. //
  3293. if ( pTask ) {
  3294. LeaveCriticalSection(&(pTask->Sync));
  3295. }
  3296. //
  3297. // remove the context from task table
  3298. //
  3299. ScepRemoveTask(pTask);
  3300. }
  3301. RpcRevertToSelf();
  3302. return((SCEPR_STATUS)rc);
  3303. }
  3304. SCEPR_STATUS
  3305. SceRpcStartTransaction(
  3306. IN SCEPR_CONTEXT Context
  3307. )
  3308. /*
  3309. Routine Description:
  3310. Start a transaction on the context. If other threads sharing the same
  3311. context, their changes will also be controlled by this transaction.
  3312. It's the caller's responsible to not share the same context for
  3313. transactioning.
  3314. Arguments:
  3315. See SceJetStartTransaction
  3316. Return Value:
  3317. SCEPR_STATUS
  3318. */
  3319. {
  3320. if ( !Context ) {
  3321. return(SCESTATUS_INVALID_PARAMETER);
  3322. }
  3323. SCESTATUS rc;
  3324. UINT ClientLocalFlag = 0;
  3325. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  3326. 0 == ClientLocalFlag ){
  3327. //
  3328. // to prevent denial-of-service type attacks,
  3329. // do not allow remote RPC
  3330. //
  3331. return SCESTATUS_ACCESS_DENIED;
  3332. }
  3333. //
  3334. // impersonate the client
  3335. //
  3336. rc = RpcImpersonateClient( NULL );
  3337. if (rc != RPC_S_OK) {
  3338. return( ScepDosErrorToSceStatus(rc) );
  3339. }
  3340. BOOL bAdminSidInToken = FALSE;
  3341. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  3342. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  3343. RpcRevertToSelf();
  3344. return SCESTATUS_SPECIAL_ACCOUNT;
  3345. }
  3346. //
  3347. // validate the context handle is a SCE context
  3348. // Only one database operation per context
  3349. //
  3350. PSCESRV_DBTASK pTask=NULL;
  3351. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  3352. SCE_TASK_LOCK,
  3353. TRUE,
  3354. &pTask);
  3355. if (SCESTATUS_SUCCESS == rc ) {
  3356. //
  3357. // lock the context
  3358. //
  3359. if ( pTask ) {
  3360. EnterCriticalSection(&(pTask->Sync));
  3361. }
  3362. //
  3363. // start transaction on this context
  3364. //
  3365. #ifdef SCE_JET_TRAN
  3366. rc = SceJetJetErrorToSceStatus(
  3367. JetSetSessionContext(
  3368. ((PSCECONTEXT)Context)->JetSessionID,
  3369. (ULONG_PTR)Context
  3370. ));
  3371. if ( SCESTATUS_SUCCESS == rc ) {
  3372. #endif
  3373. rc = SceJetStartTransaction(
  3374. (PSCECONTEXT)Context
  3375. );
  3376. #ifdef SCE_JET_TRAN
  3377. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  3378. }
  3379. #endif
  3380. //
  3381. // unlock the context
  3382. //
  3383. if ( pTask ) {
  3384. LeaveCriticalSection(&(pTask->Sync));
  3385. }
  3386. //
  3387. // remove the context from task table
  3388. //
  3389. ScepRemoveTask(pTask);
  3390. }
  3391. RpcRevertToSelf();
  3392. return((SCEPR_STATUS)rc);
  3393. }
  3394. SCEPR_STATUS
  3395. SceRpcCommitTransaction(
  3396. IN SCEPR_CONTEXT Context
  3397. )
  3398. /*
  3399. Routine Description:
  3400. Commit a transaction on the context. If other threads sharing the same
  3401. context, their changes will also be controlled by this transaction.
  3402. It's the caller's responsible to not share the same context for
  3403. transactioning.
  3404. Arguments:
  3405. See SceJetCommitTransaction
  3406. Return Value:
  3407. SCEPR_STATUS
  3408. */
  3409. {
  3410. if ( !Context ) {
  3411. return(SCESTATUS_INVALID_PARAMETER);
  3412. }
  3413. SCESTATUS rc;
  3414. UINT ClientLocalFlag = 0;
  3415. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  3416. 0 == ClientLocalFlag ){
  3417. //
  3418. // to prevent denial-of-service type attacks,
  3419. // do not allow remote RPC
  3420. //
  3421. return SCESTATUS_ACCESS_DENIED;
  3422. }
  3423. //
  3424. // impersonate the client
  3425. //
  3426. rc = RpcImpersonateClient( NULL );
  3427. if (rc != RPC_S_OK) {
  3428. return( ScepDosErrorToSceStatus(rc) );
  3429. }
  3430. BOOL bAdminSidInToken = FALSE;
  3431. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  3432. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  3433. RpcRevertToSelf();
  3434. return SCESTATUS_SPECIAL_ACCOUNT;
  3435. }
  3436. //
  3437. // validate the context handle is a SCE context
  3438. // Only one database operation per context
  3439. //
  3440. PSCESRV_DBTASK pTask=NULL;
  3441. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  3442. SCE_TASK_LOCK,
  3443. TRUE,
  3444. &pTask);
  3445. if (SCESTATUS_SUCCESS == rc ) {
  3446. //
  3447. // lock the context
  3448. //
  3449. if ( pTask ) {
  3450. EnterCriticalSection(&(pTask->Sync));
  3451. }
  3452. //
  3453. // set the context to the jet session so thread id is not used for this
  3454. // operation.
  3455. //
  3456. #ifdef SCE_JET_TRAN
  3457. rc = SceJetJetErrorToSceStatus(
  3458. JetSetSessionContext(
  3459. ((PSCECONTEXT)Context)->JetSessionID,
  3460. (ULONG_PTR)Context
  3461. ));
  3462. if ( SCESTATUS_SUCCESS == rc ) {
  3463. #endif
  3464. //
  3465. // commit transaction on this context
  3466. //
  3467. rc = SceJetCommitTransaction(
  3468. (PSCECONTEXT)Context,
  3469. 0
  3470. );
  3471. #ifdef SCE_JET_TRAN
  3472. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  3473. }
  3474. #endif
  3475. //
  3476. // unlock the context
  3477. //
  3478. if ( pTask ) {
  3479. LeaveCriticalSection(&(pTask->Sync));
  3480. }
  3481. //
  3482. // remove the context from task table
  3483. //
  3484. ScepRemoveTask(pTask);
  3485. }
  3486. RpcRevertToSelf();
  3487. return((SCEPR_STATUS)rc);
  3488. }
  3489. SCEPR_STATUS
  3490. SceRpcRollbackTransaction(
  3491. IN SCEPR_CONTEXT Context
  3492. )
  3493. /*
  3494. Routine Description:
  3495. Rollback a transaction on the context. If other threads sharing the same
  3496. context, their changes will also be controlled by this transaction.
  3497. It's the caller's responsible to not share the same context for
  3498. transactioning.
  3499. Arguments:
  3500. See SceJetRollback
  3501. Return Value:
  3502. SCEPR_STATUS
  3503. */
  3504. {
  3505. if ( !Context ) {
  3506. return(SCESTATUS_INVALID_PARAMETER);
  3507. }
  3508. SCESTATUS rc;
  3509. UINT ClientLocalFlag = 0;
  3510. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  3511. 0 == ClientLocalFlag ){
  3512. //
  3513. // to prevent denial-of-service type attacks,
  3514. // do not allow remote RPC
  3515. //
  3516. return SCESTATUS_ACCESS_DENIED;
  3517. }
  3518. //
  3519. // impersonate the client
  3520. //
  3521. rc = RpcImpersonateClient( NULL );
  3522. if (rc != RPC_S_OK) {
  3523. return( ScepDosErrorToSceStatus(rc) );
  3524. }
  3525. BOOL bAdminSidInToken = FALSE;
  3526. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  3527. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  3528. RpcRevertToSelf();
  3529. return SCESTATUS_SPECIAL_ACCOUNT;
  3530. }
  3531. //
  3532. // validate the context handle is a SCE context
  3533. // Only one database operation per context
  3534. //
  3535. PSCESRV_DBTASK pTask=NULL;
  3536. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  3537. SCE_TASK_LOCK,
  3538. TRUE,
  3539. &pTask);
  3540. if (SCESTATUS_SUCCESS == rc ) {
  3541. //
  3542. // lock the context
  3543. //
  3544. if ( pTask ) {
  3545. EnterCriticalSection(&(pTask->Sync));
  3546. }
  3547. //
  3548. // set the context to the jet session so thread id is not used for this
  3549. // operation.
  3550. //
  3551. #ifdef SCE_JET_TRAN
  3552. rc = SceJetJetErrorToSceStatus(
  3553. JetSetSessionContext(
  3554. ((PSCECONTEXT)Context)->JetSessionID,
  3555. (ULONG_PTR)Context
  3556. ));
  3557. if ( SCESTATUS_SUCCESS == rc ) {
  3558. #endif
  3559. //
  3560. // rollback transaction on this context
  3561. //
  3562. rc = SceJetRollback(
  3563. (PSCECONTEXT)Context,
  3564. 0
  3565. );
  3566. #ifdef SCE_JET_TRAN
  3567. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  3568. }
  3569. #endif
  3570. //
  3571. // unlock the context
  3572. //
  3573. if ( pTask ) {
  3574. LeaveCriticalSection(&(pTask->Sync));
  3575. }
  3576. //
  3577. // remove the context from task table
  3578. //
  3579. ScepRemoveTask(pTask);
  3580. }
  3581. RpcRevertToSelf();
  3582. return((SCEPR_STATUS)rc);
  3583. }
  3584. SCEPR_STATUS
  3585. SceRpcGetServerProductType(
  3586. IN handle_t binding_h,
  3587. OUT PSCEPR_SERVER_TYPE srvProduct
  3588. )
  3589. /*
  3590. Routine Description:
  3591. Get SCE server's product type
  3592. Arguments:
  3593. Return Value:
  3594. */
  3595. {
  3596. if ( !srvProduct ) {
  3597. return(SCESTATUS_INVALID_PARAMETER);
  3598. }
  3599. UINT ClientLocalFlag = 0;
  3600. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  3601. 0 == ClientLocalFlag ){
  3602. //
  3603. // to prevent denial-of-service type attacks,
  3604. // do not allow remote RPC
  3605. //
  3606. return SCESTATUS_ACCESS_DENIED;
  3607. }
  3608. if ( bStopRequest ) {
  3609. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  3610. }
  3611. //
  3612. // impersonate the client
  3613. //
  3614. BOOL bAdminSidInToken = FALSE;
  3615. DWORD rc = RpcImpersonateClient( NULL );
  3616. if (rc != RPC_S_OK) {
  3617. return( ScepDosErrorToSceStatus(rc) );
  3618. }
  3619. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  3620. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  3621. RpcRevertToSelf();
  3622. return SCESTATUS_SPECIAL_ACCOUNT;
  3623. }
  3624. ScepGetProductType((PSCE_SERVER_TYPE)srvProduct);
  3625. RpcRevertToSelf();
  3626. return(SCESTATUS_SUCCESS);
  3627. }
  3628. SCEPR_STATUS
  3629. SceSvcRpcUpdateInfo(
  3630. IN SCEPR_CONTEXT Context,
  3631. IN wchar_t *ServiceName,
  3632. IN PSCEPR_SVCINFO Info
  3633. )
  3634. /*
  3635. Routine Description:
  3636. Update information for the service to the database.
  3637. Arguments:
  3638. Context - the context handle
  3639. ServiceName - the service name for which info is requested
  3640. Info - output buffer
  3641. Return Value:
  3642. SCEPR_STATUS
  3643. */
  3644. {
  3645. if ( !Context || !ServiceName || !Info ) {
  3646. return(SCESTATUS_INVALID_PARAMETER);
  3647. }
  3648. SCESTATUS rc;
  3649. UINT ClientLocalFlag = 0;
  3650. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  3651. 0 == ClientLocalFlag ){
  3652. //
  3653. // to prevent denial-of-service type attacks,
  3654. // do not allow remote RPC
  3655. //
  3656. return SCESTATUS_ACCESS_DENIED;
  3657. }
  3658. //
  3659. // impersonate the client
  3660. //
  3661. rc = RpcImpersonateClient( NULL );
  3662. if (rc != RPC_S_OK) {
  3663. return( ScepDosErrorToSceStatus(rc) );
  3664. }
  3665. BOOL bAdminSidInToken = FALSE;
  3666. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  3667. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  3668. RpcRevertToSelf();
  3669. return SCESTATUS_SPECIAL_ACCOUNT;
  3670. }
  3671. //
  3672. // validate the context handle is a SCE context
  3673. // Only one database operation per context
  3674. //
  3675. PSCESRV_DBTASK pTask=NULL;
  3676. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  3677. SCE_TASK_LOCK,
  3678. TRUE,
  3679. &pTask);
  3680. if (SCESTATUS_SUCCESS == rc ) {
  3681. //
  3682. // lock the context
  3683. //
  3684. if ( pTask ) {
  3685. EnterCriticalSection(&(pTask->Sync));
  3686. }
  3687. #ifdef SCE_JET_TRAN
  3688. rc = SceJetJetErrorToSceStatus(
  3689. JetSetSessionContext(
  3690. ((PSCECONTEXT)Context)->JetSessionID,
  3691. (ULONG_PTR)Context
  3692. ));
  3693. if ( SCESTATUS_SUCCESS == rc ) {
  3694. #endif
  3695. //
  3696. // update the service info now
  3697. //
  3698. __try {
  3699. rc = SceSvcpUpdateInfo(
  3700. (PSCECONTEXT)Context,
  3701. (LPCTSTR)ServiceName,
  3702. (PSCESVC_CONFIGURATION_INFO)Info
  3703. );
  3704. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3705. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  3706. }
  3707. #ifdef SCE_JET_TRAN
  3708. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  3709. }
  3710. #endif
  3711. //
  3712. // unlock the context
  3713. //
  3714. if ( pTask ) {
  3715. LeaveCriticalSection(&(pTask->Sync));
  3716. }
  3717. //
  3718. // remove the context from task table
  3719. //
  3720. ScepRemoveTask(pTask);
  3721. }
  3722. RpcRevertToSelf();
  3723. return((SCEPR_STATUS)rc);
  3724. }
  3725. SCEPR_STATUS
  3726. SceRpcCopyObjects(
  3727. IN SCEPR_CONTEXT Context,
  3728. IN SCEPR_TYPE ProfileType,
  3729. IN wchar_t *InfFileName,
  3730. IN AREAPR Area,
  3731. OUT PSCEPR_ERROR_LOG_INFO *pErrlog OPTIONAL
  3732. )
  3733. /*
  3734. Routine Description:
  3735. Update information for the service to the database.
  3736. Arguments:
  3737. Context - the context handle
  3738. InfFileName - the inf template name to copy to
  3739. Area - which area(s) to copy
  3740. pErrlog - the error log buffer
  3741. Return Value:
  3742. SCEPR_STATUS
  3743. */
  3744. {
  3745. if ( !Context || !InfFileName ) {
  3746. return(SCESTATUS_INVALID_PARAMETER);
  3747. }
  3748. UINT ClientLocalFlag = 0;
  3749. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  3750. 0 == ClientLocalFlag ){
  3751. //
  3752. // to prevent denial-of-service type attacks,
  3753. // do not allow remote RPC
  3754. //
  3755. return SCESTATUS_ACCESS_DENIED;
  3756. }
  3757. if ( !Area ) {
  3758. //
  3759. // nothing to copy
  3760. //
  3761. return(SCESTATUS_SUCCESS);
  3762. }
  3763. if ( ProfileType != SCE_ENGINE_SCP &&
  3764. ProfileType != SCE_ENGINE_SMP ) {
  3765. return(SCESTATUS_INVALID_PARAMETER);
  3766. }
  3767. //
  3768. // impersonate the client
  3769. //
  3770. SCESTATUS rc;
  3771. rc = RpcImpersonateClient( NULL );
  3772. if (rc != RPC_S_OK) {
  3773. return( ScepDosErrorToSceStatus(rc) );
  3774. }
  3775. BOOL bAdminSidInToken = FALSE;
  3776. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  3777. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  3778. RpcRevertToSelf();
  3779. return SCESTATUS_SPECIAL_ACCOUNT;
  3780. }
  3781. //
  3782. // validate the context handle is a SCE context
  3783. // Only one database operation per context
  3784. //
  3785. PSCESRV_DBTASK pTask=NULL;
  3786. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  3787. SCE_TASK_LOCK,
  3788. FALSE,
  3789. &pTask);
  3790. if (SCESTATUS_SUCCESS == rc ) {
  3791. //
  3792. // lock the context
  3793. //
  3794. if ( pTask ) {
  3795. EnterCriticalSection(&(pTask->Sync));
  3796. }
  3797. #ifdef SCE_JET_TRAN
  3798. rc = SceJetJetErrorToSceStatus(
  3799. JetSetSessionContext(
  3800. ((PSCECONTEXT)Context)->JetSessionID,
  3801. (ULONG_PTR)Context
  3802. ));
  3803. if ( SCESTATUS_SUCCESS == rc ) {
  3804. #endif
  3805. //
  3806. // query the information now
  3807. //
  3808. if ( Area & AREA_REGISTRY_SECURITY ) {
  3809. rc = ScepCopyObjects(
  3810. (PSCECONTEXT)Context,
  3811. (SCETYPE)ProfileType,
  3812. (LPTSTR)InfFileName,
  3813. szRegistryKeys,
  3814. AREA_REGISTRY_SECURITY,
  3815. (PSCE_ERROR_LOG_INFO *)pErrlog
  3816. );
  3817. }
  3818. if ( SCESTATUS_SUCCESS == rc &&
  3819. Area & AREA_FILE_SECURITY ) {
  3820. rc = ScepCopyObjects(
  3821. (PSCECONTEXT)Context,
  3822. (SCETYPE)ProfileType,
  3823. (LPTSTR)InfFileName,
  3824. szFileSecurity,
  3825. AREA_FILE_SECURITY,
  3826. (PSCE_ERROR_LOG_INFO *)pErrlog
  3827. );
  3828. }
  3829. #if 0
  3830. if ( SCESTATUS_SUCCESS == rc &&
  3831. Area & AREA_DS_OBJECTS ) {
  3832. rc = ScepCopyObjects(
  3833. (PSCECONTEXT)Context,
  3834. (SCETYPE)ProfileType,
  3835. (LPTSTR)InfFileName,
  3836. szDSSecurity,
  3837. AREA_DS_OBJECTS,
  3838. (PSCE_ERROR_LOG_INFO *)pErrlog
  3839. );
  3840. }
  3841. #endif
  3842. if ( SCESTATUS_SUCCESS == rc &&
  3843. Area & AREA_SYSTEM_SERVICE ) {
  3844. rc = ScepCopyObjects(
  3845. (PSCECONTEXT)Context,
  3846. (SCETYPE)ProfileType,
  3847. (LPTSTR)InfFileName,
  3848. szServiceGeneral,
  3849. AREA_SYSTEM_SERVICE,
  3850. (PSCE_ERROR_LOG_INFO *)pErrlog
  3851. );
  3852. }
  3853. SCESVC_INFO_TYPE iType;
  3854. switch ( ProfileType ) {
  3855. case SCE_ENGINE_SCP:
  3856. iType = SceSvcMergedPolicyInfo;
  3857. break;
  3858. case SCE_ENGINE_SMP:
  3859. iType = SceSvcConfigurationInfo;
  3860. break;
  3861. }
  3862. if ( SCESTATUS_SUCCESS == rc &&
  3863. ( Area & AREA_SYSTEM_SERVICE) ) {
  3864. rc = ScepGenerateAttachmentSections(
  3865. (PSCECONTEXT)Context,
  3866. iType,
  3867. (LPTSTR)InfFileName,
  3868. SCE_ATTACHMENT_SERVICE
  3869. );
  3870. }
  3871. if ( SCESTATUS_SUCCESS == rc &&
  3872. (Area & AREA_SECURITY_POLICY) ) {
  3873. rc = ScepGenerateAttachmentSections(
  3874. (PSCECONTEXT)Context,
  3875. iType,
  3876. (LPTSTR)InfFileName,
  3877. SCE_ATTACHMENT_POLICY
  3878. );
  3879. }
  3880. if ( SCESTATUS_SUCCESS == rc &&
  3881. ( Area & AREA_ATTACHMENTS) ) {
  3882. rc = ScepGenerateWMIAttachmentSections(
  3883. (PSCECONTEXT)Context,
  3884. iType,
  3885. (LPTSTR)InfFileName
  3886. );
  3887. }
  3888. #ifdef SCE_JET_TRAN
  3889. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  3890. }
  3891. #endif
  3892. //
  3893. // unlock the context
  3894. //
  3895. if ( pTask ) {
  3896. LeaveCriticalSection(&(pTask->Sync));
  3897. }
  3898. //
  3899. // remove the context from task table
  3900. //
  3901. ScepRemoveTask(pTask);
  3902. }
  3903. RpcRevertToSelf();
  3904. return((SCEPR_STATUS)rc);
  3905. }
  3906. SCEPR_STATUS
  3907. SceRpcSetupResetLocalPolicy(
  3908. IN SCEPR_CONTEXT Context,
  3909. IN AREAPR Area,
  3910. IN wchar_t *OneSectionName OPTIONAL,
  3911. IN DWORD PolicyOptions
  3912. )
  3913. {
  3914. SCESTATUS rc;
  3915. UINT ClientLocalFlag = 0;
  3916. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  3917. 0 == ClientLocalFlag ){
  3918. //
  3919. // to prevent denial-of-service type attacks,
  3920. // do not allow remote RPC
  3921. //
  3922. return SCESTATUS_ACCESS_DENIED;
  3923. }
  3924. //
  3925. // impersonate the client
  3926. //
  3927. rc = RpcImpersonateClient( NULL );
  3928. if (rc != RPC_S_OK) {
  3929. return( ScepDosErrorToSceStatus(rc) );
  3930. }
  3931. BOOL bAdminSidInToken = FALSE;
  3932. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  3933. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  3934. RpcRevertToSelf();
  3935. return SCESTATUS_SPECIAL_ACCOUNT;
  3936. }
  3937. //
  3938. // validate the context handle is a SCE context
  3939. // Only one database operation per context
  3940. //
  3941. PSCESRV_DBTASK pTask=NULL;
  3942. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  3943. SCE_TASK_LOCK,
  3944. TRUE,
  3945. &pTask);
  3946. if (SCESTATUS_SUCCESS == rc ) {
  3947. //
  3948. // lock the context
  3949. //
  3950. if ( pTask ) {
  3951. EnterCriticalSection(&(pTask->Sync));
  3952. }
  3953. #ifdef SCE_JET_TRAN
  3954. rc = SceJetJetErrorToSceStatus(
  3955. JetSetSessionContext(
  3956. ((PSCECONTEXT)Context)->JetSessionID,
  3957. (ULONG_PTR)Context
  3958. ));
  3959. if ( SCESTATUS_SUCCESS == rc ) {
  3960. #endif
  3961. //
  3962. // remove policies from the local table
  3963. //
  3964. if ( PolicyOptions & SCE_RESET_POLICY_SYSPREP ) {
  3965. ScepSetupResetLocalPolicy((PSCECONTEXT)Context,
  3966. (AREA_INFORMATION)Area,
  3967. NULL,
  3968. SCE_ENGINE_SMP,
  3969. FALSE
  3970. );
  3971. ScepSetupResetLocalPolicy((PSCECONTEXT)Context,
  3972. (AREA_INFORMATION)Area,
  3973. NULL,
  3974. SCE_ENGINE_SCP,
  3975. FALSE
  3976. );
  3977. rc = ScepSetupResetLocalPolicy((PSCECONTEXT)Context,
  3978. (AREA_INFORMATION)Area,
  3979. NULL,
  3980. SCE_ENGINE_SAP, // for the tattoo table
  3981. FALSE
  3982. );
  3983. } else {
  3984. if ( PolicyOptions & SCE_RESET_POLICY_TATTOO ) {
  3985. // after dcpromo, we need to reset the tattoo values
  3986. rc = ScepSetupResetLocalPolicy((PSCECONTEXT)Context,
  3987. (AREA_INFORMATION)Area,
  3988. (PCWSTR)OneSectionName,
  3989. SCE_ENGINE_SAP, // for the tattoo table
  3990. FALSE
  3991. );
  3992. }
  3993. rc = ScepSetupResetLocalPolicy((PSCECONTEXT)Context,
  3994. (AREA_INFORMATION)Area,
  3995. (PCWSTR)OneSectionName,
  3996. SCE_ENGINE_SMP,
  3997. (PolicyOptions & SCE_RESET_POLICY_KEEP_LOCAL)
  3998. );
  3999. if ( (PolicyOptions & SCE_RESET_POLICY_ENFORCE_ATREBOOT ) &&
  4000. ( (((PSCECONTEXT)Context)->Type & 0xF0L) == SCEJET_MERGE_TABLE_1 ||
  4001. (((PSCECONTEXT)Context)->Type & 0xF0L) == SCEJET_MERGE_TABLE_2 ) &&
  4002. ((PSCECONTEXT)Context)->JetScpID != ((PSCECONTEXT)Context)->JetSmpID ) {
  4003. //
  4004. // there is effective policy table already in the database
  4005. // (and this is in setup upgrade)
  4006. // update local group policy table to trigger a policy prop at reboot
  4007. //
  4008. ScepEnforcePolicyPropagation();
  4009. }
  4010. }
  4011. #ifdef SCE_JET_TRAN
  4012. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  4013. }
  4014. #endif
  4015. //
  4016. // unlock the context
  4017. //
  4018. if ( pTask ) {
  4019. LeaveCriticalSection(&(pTask->Sync));
  4020. }
  4021. //
  4022. // remove the context from task table
  4023. //
  4024. ScepRemoveTask(pTask);
  4025. }
  4026. RpcRevertToSelf();
  4027. return((SCEPR_STATUS)rc);
  4028. }
  4029. SCESTATUS
  4030. ScepGenerateAttachmentSections(
  4031. IN PSCECONTEXT hProfile,
  4032. IN SCESVC_INFO_TYPE InfoType,
  4033. IN LPTSTR InfFileName,
  4034. IN SCE_ATTACHMENT_TYPE aType
  4035. )
  4036. {
  4037. SCESTATUS rc;
  4038. PSCE_SERVICES pServiceList=NULL, pNode;
  4039. rc = ScepEnumServiceEngines( &pServiceList, aType );
  4040. if ( rc == SCESTATUS_SUCCESS ) {
  4041. for ( pNode=pServiceList; pNode != NULL; pNode=pNode->Next) {
  4042. //
  4043. // generate section for one attachment
  4044. //
  4045. rc = ScepGenerateOneAttachmentSection(hProfile,
  4046. InfoType,
  4047. InfFileName,
  4048. pNode->ServiceName,
  4049. FALSE
  4050. );
  4051. if ( rc != SCESTATUS_SUCCESS ) {
  4052. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  4053. SCEDLL_ERROR_CONVERT_SECTION, pNode->ServiceName );
  4054. break;
  4055. }
  4056. }
  4057. SceFreePSCE_SERVICES(pServiceList);
  4058. }
  4059. if ( rc == SCESTATUS_PROFILE_NOT_FOUND ||
  4060. rc == SCESTATUS_RECORD_NOT_FOUND ) {
  4061. // if no service exist, just ignore
  4062. rc = SCESTATUS_SUCCESS;
  4063. }
  4064. return(rc);
  4065. }
  4066. SCESTATUS
  4067. ScepGenerateWMIAttachmentSections(
  4068. IN PSCECONTEXT hProfile,
  4069. IN SCESVC_INFO_TYPE InfoType,
  4070. IN LPTSTR InfFileName
  4071. )
  4072. {
  4073. SCESTATUS rc;
  4074. PSCE_NAME_LIST pList=NULL, pNode;
  4075. rc = ScepEnumAttachmentSections( hProfile, &pList);
  4076. if ( rc == SCESTATUS_SUCCESS ) {
  4077. for ( pNode=pList; pNode != NULL; pNode=pNode->Next) {
  4078. //
  4079. // generate section for one attachment
  4080. //
  4081. rc = ScepGenerateOneAttachmentSection(hProfile,
  4082. InfoType,
  4083. InfFileName,
  4084. pNode->Name,
  4085. TRUE
  4086. );
  4087. if ( rc != SCESTATUS_SUCCESS ) {
  4088. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  4089. SCEDLL_ERROR_CONVERT_SECTION, pNode->Name );
  4090. break;
  4091. }
  4092. }
  4093. ScepFreeNameList(pList);
  4094. }
  4095. if ( rc == SCESTATUS_PROFILE_NOT_FOUND ||
  4096. rc == SCESTATUS_RECORD_NOT_FOUND ) {
  4097. // if no service exist, just ignore
  4098. rc = SCESTATUS_SUCCESS;
  4099. }
  4100. return(rc);
  4101. }
  4102. SCESTATUS
  4103. ScepGenerateOneAttachmentSection(
  4104. IN PSCECONTEXT hProfile,
  4105. IN SCESVC_INFO_TYPE InfoType,
  4106. IN LPTSTR InfFileName,
  4107. IN LPTSTR SectionName,
  4108. IN BOOL bWMISection
  4109. )
  4110. {
  4111. //
  4112. // read inf info for the section
  4113. //
  4114. SCESTATUS rc;
  4115. SCE_ENUMERATION_CONTEXT sceEnumHandle=0;
  4116. DWORD CountReturned;
  4117. PSCESVC_CONFIGURATION_INFO pAttachInfo=NULL;
  4118. do {
  4119. CountReturned = 0;
  4120. rc = SceSvcpQueryInfo(
  4121. hProfile,
  4122. InfoType,
  4123. SectionName,
  4124. NULL,
  4125. FALSE,
  4126. (PVOID *)&pAttachInfo,
  4127. &sceEnumHandle
  4128. );
  4129. if ( rc == SCESTATUS_SUCCESS && pAttachInfo != NULL &&
  4130. pAttachInfo->Count > 0 ) {
  4131. //
  4132. // got something
  4133. //
  4134. CountReturned = pAttachInfo->Count;
  4135. //
  4136. // copy each line
  4137. //
  4138. for ( DWORD i=0; i<pAttachInfo->Count; i++ ) {
  4139. if ( pAttachInfo->Lines[i].Key == NULL ||
  4140. pAttachInfo->Lines[i].Value == NULL ) {
  4141. continue;
  4142. }
  4143. if ( !WritePrivateProfileString(
  4144. SectionName,
  4145. pAttachInfo->Lines[i].Key,
  4146. pAttachInfo->Lines[i].Value,
  4147. InfFileName
  4148. ) ) {
  4149. rc = ScepDosErrorToSceStatus(GetLastError());
  4150. break;
  4151. }
  4152. }
  4153. if ( bWMISection ) {
  4154. //
  4155. // make sure to create the szAttachments section
  4156. //
  4157. if ( !WritePrivateProfileString(
  4158. szAttachments,
  4159. SectionName,
  4160. L"Include",
  4161. InfFileName
  4162. ) ) {
  4163. rc = ScepDosErrorToSceStatus(GetLastError());
  4164. }
  4165. }
  4166. }
  4167. SceSvcpFreeMemory((PVOID)pAttachInfo);
  4168. pAttachInfo = NULL;
  4169. } while ( rc == SCESTATUS_SUCCESS && CountReturned > 0 );
  4170. if ( SCESTATUS_RECORD_NOT_FOUND == rc ) {
  4171. rc = SCESTATUS_SUCCESS;
  4172. }
  4173. return rc;
  4174. }
  4175. void __RPC_USER
  4176. SCEPR_CONTEXT_rundown( SCEPR_CONTEXT Context)
  4177. {
  4178. SCESTATUS rc;
  4179. //
  4180. // impersonate the client
  4181. //
  4182. rc = RpcImpersonateClient( NULL );
  4183. if (rc != RPC_S_OK) {
  4184. return;
  4185. }
  4186. //
  4187. // this client is shutting down
  4188. //
  4189. rc = ScepValidateAndCloseDatabase((PSCECONTEXT)Context);
  4190. RpcRevertToSelf();
  4191. return;
  4192. }
  4193. SCESTATUS
  4194. ScepOpenDatabase(
  4195. IN PCWSTR DatabaseName,
  4196. IN DWORD OpenOption,
  4197. IN SCEJET_OPEN_TYPE OpenType,
  4198. OUT PSCECONTEXT *pContext
  4199. )
  4200. /*
  4201. Routine Description:
  4202. This routine opens the database and returns a context handle.
  4203. OpenDatabase can be called by multiple clients for the same database
  4204. and we do not block multiple access because each client will get
  4205. a duplicate database cursor and have their own working tables.
  4206. When a database is changed by other clients, all cursors will be
  4207. synchronized. Clients who had retrived "old" data are responsible
  4208. to refresh their data buffer. No notification is provided at this
  4209. point.
  4210. Arguments:
  4211. Return Value:
  4212. */
  4213. {
  4214. if ( !DatabaseName || !pContext ) {
  4215. return(SCESTATUS_INVALID_PARAMETER);
  4216. }
  4217. SCESTATUS rc;
  4218. //
  4219. // check access of the database (with current client token)
  4220. //
  4221. DWORD Access=0;
  4222. if ( SCEJET_OPEN_READ_ONLY == OpenType ) {
  4223. // BUG in ESENT
  4224. // Even ask for read only, ESENT still writes to the database
  4225. // Access = FILE_GENERIC_READ;
  4226. Access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
  4227. } else {
  4228. Access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
  4229. }
  4230. rc = ScepDatabaseAccessGranted((LPTSTR)DatabaseName,
  4231. Access,
  4232. FALSE
  4233. );
  4234. if ( rc != ERROR_SUCCESS ) {
  4235. ScepLogOutput2(1,rc,L"%s", DatabaseName);
  4236. return( ScepDosErrorToSceStatus(rc) );
  4237. }
  4238. DWORD Len;
  4239. DWORD MBLen=0;
  4240. PCHAR FileName=NULL;
  4241. NTSTATUS NtStatus;
  4242. //
  4243. // convert WCHAR into ANSI
  4244. //
  4245. Len = wcslen( DatabaseName );
  4246. NtStatus = RtlUnicodeToMultiByteSize(&MBLen, (PWSTR)DatabaseName, Len*sizeof(WCHAR));
  4247. if ( !NT_SUCCESS(NtStatus) ) {
  4248. //
  4249. // cannot get the length, set default to 512
  4250. //
  4251. MBLen = 512;
  4252. }
  4253. FileName = (PCHAR)ScepAlloc( LPTR, MBLen+2);
  4254. if ( FileName == NULL ) {
  4255. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4256. } else {
  4257. NtStatus = RtlUnicodeToMultiByteN(
  4258. FileName,
  4259. MBLen+1,
  4260. NULL,
  4261. (PWSTR)DatabaseName,
  4262. Len*sizeof(WCHAR)
  4263. );
  4264. if ( !NT_SUCCESS(NtStatus) ) {
  4265. rc = SCESTATUS_PROFILE_NOT_FOUND;
  4266. } else {
  4267. //
  4268. // make sure the context buffer is initialized
  4269. //
  4270. *pContext = NULL;
  4271. rc = SceJetOpenFile(
  4272. (LPSTR)FileName,
  4273. OpenType, //SCEJET_OPEN_READ_WRITE,
  4274. (OpenOption == SCE_OPEN_OPTION_TATTOO ) ? SCE_TABLE_OPTION_TATTOO : 0,
  4275. pContext
  4276. );
  4277. if ( (OpenOption == SCE_OPEN_OPTION_REQUIRE_ANALYSIS ) &&
  4278. SCESTATUS_SUCCESS == rc &&
  4279. *pContext ) {
  4280. if ( (*pContext)->JetSapID == JET_tableidNil ) {
  4281. //
  4282. // no analysis information is available
  4283. //
  4284. rc = SCESTATUS_PROFILE_NOT_FOUND;
  4285. //
  4286. // free handle
  4287. //
  4288. SceJetCloseFile(
  4289. *pContext,
  4290. TRUE,
  4291. FALSE
  4292. );
  4293. *pContext = NULL;
  4294. }
  4295. }
  4296. }
  4297. ScepFree( FileName );
  4298. }
  4299. return(rc);
  4300. }
  4301. SCESTATUS
  4302. ScepCloseDatabase(
  4303. IN PSCECONTEXT Context
  4304. )
  4305. {
  4306. SCESTATUS rc;
  4307. if ( !Context ) {
  4308. return(SCESTATUS_INVALID_PARAMETER);
  4309. }
  4310. __try {
  4311. if ( ScepIsValidContext(Context) ) {
  4312. //
  4313. // be able to access the first byte
  4314. //
  4315. rc = SceJetCloseFile(
  4316. Context,
  4317. TRUE,
  4318. FALSE
  4319. );
  4320. } else {
  4321. //
  4322. // this context is not our context or already be freed
  4323. //
  4324. rc = SCESTATUS_INVALID_PARAMETER;
  4325. }
  4326. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4327. rc = SCESTATUS_INVALID_PARAMETER;
  4328. }
  4329. return(rc);
  4330. }
  4331. DWORD
  4332. SceRpcControlNotificationQProcess(
  4333. IN handle_t binding_h,
  4334. IN DWORD Flag
  4335. )
  4336. /*
  4337. Description:
  4338. This function should be called by a system thread to control that policy
  4339. notification queue process should be suspended or resumed.
  4340. The purpose of this function is to protect policy changes being overwritten
  4341. by policy proapgation when the GPO file is copied/imported into the database
  4342. */
  4343. {
  4344. UINT ClientLocalFlag = 0;
  4345. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  4346. 0 == ClientLocalFlag ){
  4347. //
  4348. // to prevent denial-of-service type attacks,
  4349. // do not allow remote RPC
  4350. //
  4351. return SCESTATUS_ACCESS_DENIED;
  4352. }
  4353. DWORD rc=ERROR_SUCCESS;
  4354. //
  4355. // impersonate the client
  4356. //
  4357. rc = RpcImpersonateClient( NULL );
  4358. if (rc != RPC_S_OK) {
  4359. ScepNotifyLogPolicy(rc, FALSE, L"Impersonation Failed", 0, 0, NULL );
  4360. return( rc );
  4361. }
  4362. //
  4363. // perform access check to make sure that only
  4364. // system thread can make the call
  4365. //
  4366. HANDLE hToken = NULL;
  4367. if (!OpenThreadToken( GetCurrentThread(),
  4368. TOKEN_QUERY,
  4369. TRUE,
  4370. &hToken)) {
  4371. rc = GetLastError();
  4372. ScepNotifyLogPolicy(rc, FALSE, L"Fail to query token", 0, 0, NULL );
  4373. RpcRevertToSelf();
  4374. return( rc );
  4375. }
  4376. BOOL b=FALSE;
  4377. rc = RtlNtStatusToDosError( ScepIsSystemContext(hToken, &b) );
  4378. if ( rc != ERROR_SUCCESS || !b ) {
  4379. CloseHandle(hToken);
  4380. ScepNotifyLogPolicy(rc, FALSE, L"Not system context", 0, 0, NULL );
  4381. RpcRevertToSelf();
  4382. return( rc ? rc : ERROR_ACCESS_DENIED );
  4383. }
  4384. CloseHandle(hToken);
  4385. //
  4386. // even though there might be a shutdown request
  4387. // we need to let the control go through
  4388. //
  4389. if ( Flag ) {
  4390. ScepNotifyLogPolicy(0, TRUE, L"RPC enter Suspend queue.", 0, 0, NULL );
  4391. //
  4392. // this thread is called from policy propagation which is guaranteed to
  4393. // run by one thread (system context). No need to protect the global buffer
  4394. //
  4395. gPolicyWaitCount++;
  4396. if ( pNotificationQHead ) {
  4397. if ( gPolicyWaitCount < SCE_POLICY_MAX_WAIT ) {
  4398. //
  4399. // queue is not empty, should not propagate policy
  4400. //
  4401. ScepNotifyLogPolicy(0, FALSE, L"Queue is not empty, abort.", 0, 0, NULL );
  4402. RpcRevertToSelf();
  4403. return (ERROR_OVERRIDE_NOCHANGES);
  4404. } else {
  4405. ScepNotifyLogPolicy(0, FALSE, L"Resetting policy wait count.", 0, 0, NULL );
  4406. gPolicyWaitCount = 0;
  4407. }
  4408. } else {
  4409. gPolicyWaitCount = 0;
  4410. }
  4411. } else {
  4412. ScepNotifyLogPolicy(0, TRUE, L"RPC enter Resume queue.", 0, 0, NULL );
  4413. }
  4414. //
  4415. // now set the control flag
  4416. //
  4417. ScepNotificationQControl(Flag);
  4418. RpcRevertToSelf();
  4419. return(rc);
  4420. }
  4421. DWORD
  4422. SceRpcNotifySaveChangesInGP(
  4423. IN handle_t binding_h,
  4424. IN DWORD DbType,
  4425. IN DWORD DeltaType,
  4426. IN DWORD ObjectType,
  4427. IN PSCEPR_SID ObjectSid OPTIONAL,
  4428. IN DWORD ExplicitLowRight,
  4429. IN DWORD ExplicitHighRight
  4430. )
  4431. /*
  4432. Description:
  4433. This function should be called by a system thread to notify that policy
  4434. in LSA/SAM databases are changed programmatically by other applications.
  4435. The purpose of this function is to synchronize policy store with LSA/SAM
  4436. databases so that application changes won't be overwritten by next
  4437. policy propagation.
  4438. This function will add the notification to a queue for server to process.
  4439. Only system context can add a node to the queue.
  4440. */
  4441. {
  4442. UINT ClientLocalFlag = 0;
  4443. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  4444. 0 == ClientLocalFlag ){
  4445. //
  4446. // to prevent denial-of-service type attacks,
  4447. // do not allow remote RPC
  4448. //
  4449. return SCESTATUS_ACCESS_DENIED;
  4450. }
  4451. //
  4452. // even though there might be a shutdown request
  4453. // we need to let notification saved before allowing shutdown
  4454. //
  4455. DWORD rc=ERROR_SUCCESS;
  4456. ScepNotifyLogPolicy(0, TRUE, L"Notified DC", DbType, ObjectType, NULL );
  4457. if ( ObjectSid ) {
  4458. __try {
  4459. if ( !RtlValidSid(ObjectSid) ) {
  4460. rc = GetLastError();
  4461. }
  4462. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4463. // objectsid buffer is invalid
  4464. rc = ERROR_EXCEPTION_IN_SERVICE;
  4465. }
  4466. if ( rc != ERROR_SUCCESS ) {
  4467. ScepNotifyLogPolicy(0, FALSE, L"Invalid Sid", DbType, ObjectType, NULL );
  4468. return(rc);
  4469. }
  4470. }
  4471. //
  4472. // impersonate the client
  4473. //
  4474. rc = RpcImpersonateClient( NULL );
  4475. if (rc != RPC_S_OK) {
  4476. ScepNotifyLogPolicy(rc, FALSE, L"Impersonation Failed", DbType, ObjectType, NULL );
  4477. return( rc );
  4478. }
  4479. //
  4480. // perform access check to make sure that only
  4481. // system thread can make the call
  4482. //
  4483. HANDLE hToken = NULL;
  4484. if (!OpenThreadToken( GetCurrentThread(),
  4485. TOKEN_QUERY,
  4486. TRUE,
  4487. &hToken)) {
  4488. rc = GetLastError();
  4489. ScepNotifyLogPolicy(rc, FALSE, L"Fail to query token", DbType, ObjectType, NULL );
  4490. RpcRevertToSelf();
  4491. return( rc );
  4492. }
  4493. BOOL b=FALSE;
  4494. rc = RtlNtStatusToDosError( ScepIsSystemContext(hToken, &b) );
  4495. if ( rc != ERROR_SUCCESS || !b ) {
  4496. CloseHandle(hToken);
  4497. ScepNotifyLogPolicy(rc, FALSE, L"Not system context", DbType, ObjectType, NULL );
  4498. RpcRevertToSelf();
  4499. return( rc ? rc : ERROR_ACCESS_DENIED );
  4500. }
  4501. CloseHandle(hToken);
  4502. //
  4503. // Add the request to the "queue" for further process
  4504. //
  4505. rc = ScepNotificationQEnqueue((SECURITY_DB_TYPE)DbType,
  4506. (SECURITY_DB_DELTA_TYPE)DeltaType,
  4507. (SECURITY_DB_OBJECT_TYPE)ObjectType,
  4508. (PSID)ObjectSid,
  4509. ExplicitLowRight,
  4510. ExplicitHighRight,
  4511. NULL
  4512. );
  4513. RpcRevertToSelf();
  4514. return(rc);
  4515. }
  4516. DWORD
  4517. ScepNotifyProcessOneNodeDC(
  4518. IN SECURITY_DB_TYPE DbType,
  4519. IN SECURITY_DB_OBJECT_TYPE ObjectType,
  4520. IN SECURITY_DB_DELTA_TYPE DeltaType,
  4521. IN PSID ObjectSid,
  4522. IN DWORD ExplicitLowRight,
  4523. IN DWORD ExplicitHighRight,
  4524. OUT BOOL *pbTimeout
  4525. )
  4526. /*
  4527. Description:
  4528. This function is called by the queue management thread to process one
  4529. notification node in the queue. This function will determine which group
  4530. policy template to save to and what are the differences between current
  4531. state of LSA/SAM and group policy.
  4532. Group policy is only modified when there is a difference detected. Group
  4533. policy version # is updated on save. This function is always called in a
  4534. single system thread.
  4535. if scecli.dll fails to be loaded, ERROR_MOD_NOT_FOUND will be returned.
  4536. if sysvol share is not ready, the error returned will be ERROR_FILE_NOT_FOUND.
  4537. However if the template file doesn't exist (deleted), ERROR_FILE_NOT_FOUND will
  4538. also be returned. This case is handled the same way as the share/path doesn't
  4539. exist (error logged and retried) because the GPOs are required to be there for
  4540. replication purpose. But in the future, when the dependency is removed from
  4541. domain controllers GPO, we might need to separate the two cases (one success,
  4542. one failure).
  4543. If disk is full, the error returned will be ERROR_EXTENDED_ERROR.
  4544. */
  4545. {
  4546. //
  4547. // query if I am in setup
  4548. //
  4549. DWORD dwInSetup = 0;
  4550. DWORD rc=0;
  4551. *pbTimeout = FALSE;
  4552. ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
  4553. TEXT("System\\Setup"),
  4554. TEXT("SystemSetupInProgress"),
  4555. &dwInSetup
  4556. );
  4557. PWSTR TemplateName=NULL;
  4558. BOOL bAccountGPO=FALSE;
  4559. if ( DbType == SecurityDbSam &&
  4560. !SCEP_IS_SAM_OBJECT(ObjectType) ) {
  4561. //
  4562. // if it's for deleted account, should update user right GPO
  4563. // otherwise, update the account GPO
  4564. //
  4565. bAccountGPO = TRUE;
  4566. }
  4567. if ( dwInSetup && !IsNT5()) {
  4568. //
  4569. // if it's in setup, group policy templates are not available (DS is down)
  4570. // save the notifications to a temperaory store and process the
  4571. // store at next system start up.
  4572. //
  4573. ScepNotifyLogPolicy(0, FALSE, L"In setup", DbType, ObjectType, NULL );
  4574. UNICODE_STRING tmp;
  4575. tmp.Length = 0;
  4576. tmp.Buffer = NULL;
  4577. //
  4578. // get the default template name
  4579. //
  4580. rc = ScepNotifyGetDefaultGPOTemplateName(
  4581. tmp,
  4582. NULL,
  4583. bAccountGPO,
  4584. SCEGPO_INSETUP_NT4,
  4585. &TemplateName
  4586. );
  4587. if ( ERROR_SUCCESS == rc && TemplateName ) {
  4588. //
  4589. // save the transaction in this temp file
  4590. //
  4591. rc = ScepNotifySaveNotifications(TemplateName,
  4592. (SECURITY_DB_TYPE)DbType,
  4593. (SECURITY_DB_OBJECT_TYPE)ObjectType,
  4594. (SECURITY_DB_DELTA_TYPE)DeltaType,
  4595. (PSID)ObjectSid
  4596. );
  4597. ScepNotifyLogPolicy(rc, FALSE, L"Notification Saved", DbType, ObjectType, TemplateName );
  4598. } else {
  4599. ScepNotifyLogPolicy(rc, FALSE, L"Error get file path", DbType, ObjectType, NULL );
  4600. }
  4601. //
  4602. // free TemplateName
  4603. //
  4604. LocalFree(TemplateName);
  4605. return rc;
  4606. }
  4607. //
  4608. // let's check if scecli is loaded in the process
  4609. // once it's loaded, it will stay loaded.
  4610. //
  4611. if ( hSceCliDll == NULL )
  4612. hSceCliDll = LoadLibrary(TEXT("scecli.dll"));
  4613. if ( hSceCliDll ) {
  4614. if ( pfSceInfWriteInfo == NULL ) {
  4615. pfSceInfWriteInfo = (PFSCEINFWRITEINFO)GetProcAddress(
  4616. hSceCliDll,
  4617. "SceWriteSecurityProfileInfo");
  4618. }
  4619. if ( pfSceGetInfo == NULL ) {
  4620. pfSceGetInfo = (PFSCEGETINFO)GetProcAddress(
  4621. hSceCliDll,
  4622. "SceGetSecurityProfileInfo");
  4623. }
  4624. }
  4625. //
  4626. // if shutdown/stop service is requested, or client functions can't be found
  4627. // quit now
  4628. //
  4629. if ( bStopRequest || !hSceCliDll ||
  4630. !pfSceInfWriteInfo || !pfSceGetInfo ) {
  4631. if ( bStopRequest ) {
  4632. ScepNotifyLogPolicy(0, FALSE, L"Leave - Stop Requested", DbType, ObjectType, NULL );
  4633. } else {
  4634. rc = ERROR_MOD_NOT_FOUND;
  4635. ScepNotifyLogPolicy(0, FALSE, L"Leave - Can't load scecli.dll or GetProcAddr", DbType, ObjectType, NULL );
  4636. }
  4637. return(rc);
  4638. }
  4639. //
  4640. // domain DNS name is required to access the sysvol portion of group policy
  4641. // templates.
  4642. //
  4643. // This information is only queried once and saved in the static global buffer.
  4644. //
  4645. if ( (DnsDomainInfo == NULL) ||
  4646. (DnsDomainInfo->DnsDomainName.Buffer == NULL) ) {
  4647. //
  4648. // free the old buffer
  4649. //
  4650. if ( DnsDomainInfo ) {
  4651. LsaFreeMemory(DnsDomainInfo);
  4652. DnsDomainInfo = NULL;
  4653. }
  4654. OBJECT_ATTRIBUTES ObjectAttributes;
  4655. LSA_HANDLE LsaPolicyHandle;
  4656. InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
  4657. NTSTATUS Status = LsaOpenPolicy( NULL,
  4658. &ObjectAttributes,
  4659. POLICY_VIEW_LOCAL_INFORMATION,
  4660. &LsaPolicyHandle );
  4661. if ( NT_SUCCESS(Status) ) {
  4662. Status = LsaQueryInformationPolicy( LsaPolicyHandle,
  4663. PolicyDnsDomainInformation,
  4664. ( PVOID * )&DnsDomainInfo );
  4665. LsaClose( LsaPolicyHandle );
  4666. }
  4667. rc = RtlNtStatusToDosError(Status);
  4668. }
  4669. //
  4670. // get the template name (full UNC path) in sysvol
  4671. //
  4672. if ( ERROR_SUCCESS == rc &&
  4673. DnsDomainInfo &&
  4674. (DnsDomainInfo->DnsDomainName.Buffer) ) {
  4675. rc = ScepNotifyGetDefaultGPOTemplateName(
  4676. (UNICODE_STRING)(DnsDomainInfo->DnsDomainName),
  4677. NULL,
  4678. bAccountGPO,
  4679. dwInSetup ? SCEGPO_INSETUP_NT5 : 0,
  4680. &TemplateName
  4681. );
  4682. }
  4683. ScepNotifyLogPolicy(rc, FALSE, L"Get template name", DbType, ObjectType, TemplateName);
  4684. if ( ERROR_SUCCESS == rc && TemplateName ) {
  4685. //
  4686. // Check to see if the current DC is advertised to be a DC and
  4687. // and synchronized with the PDC policy
  4688. //
  4689. // Note, this check is bypassed in setup, is only done for the
  4690. // domain controller GPO, and for every 10 nodes processed
  4691. //
  4692. if ( gdwRequirePDCSync && (dwInSetup == 0) && !bAccountGPO &&
  4693. !gbCheckSync ) {
  4694. if ( ERROR_SUCCESS != ( rc = ScepWaitForSynchronizeWithPDC(
  4695. (UNICODE_STRING)(DnsDomainInfo->DnsDomainName),
  4696. TemplateName,
  4697. pbTimeout)) ) {
  4698. if ( *pbTimeout ) {
  4699. //
  4700. // we ran into maximum time out, must return and drop all nodes
  4701. // free TemplateName
  4702. //
  4703. LocalFree(TemplateName);
  4704. return rc;
  4705. } else {
  4706. //
  4707. // logs an event and let the change go through
  4708. //
  4709. LogEvent(MyModuleHandle,
  4710. STATUS_SEVERITY_ERROR,
  4711. SCEEVENT_ERROR_POLICY_PDCVERIFY,
  4712. SCESRV_POLICY_ERROR_VERIFY_SYNC,
  4713. rc
  4714. );
  4715. }
  4716. }
  4717. //
  4718. // PDC is already checked, set the flag now
  4719. //
  4720. gbCheckSync = TRUE;
  4721. }
  4722. AREA_INFORMATION Area;
  4723. PSCE_PROFILE_INFO pSceInfo=NULL;
  4724. //
  4725. // open template to get the existing template info
  4726. //
  4727. SCE_HINF hProfile;
  4728. hProfile.Type = (BYTE)SCE_INF_FORMAT;
  4729. rc = SceInfpOpenProfile(
  4730. TemplateName,
  4731. &(hProfile.hInf)
  4732. );
  4733. rc = ScepSceStatusToDosError(rc);
  4734. if ( ERROR_SUCCESS == rc ) {
  4735. if ( (DbType == SecurityDbLsa &&
  4736. ObjectType == SecurityDbObjectLsaAccount) ||
  4737. (DbType == SecurityDbSam &&
  4738. (ObjectType == SecurityDbObjectSamUser ||
  4739. ObjectType == SecurityDbObjectSamGroup ||
  4740. ObjectType == SecurityDbObjectSamAlias )) ) {
  4741. Area = AREA_ATTACHMENTS; // just create the buffer;
  4742. } else {
  4743. Area = AREA_SECURITY_POLICY;
  4744. }
  4745. //
  4746. // load informatin from the template (GP)
  4747. //
  4748. rc = (*pfSceGetInfo)(
  4749. (PVOID)&hProfile,
  4750. SCE_ENGINE_SCP,
  4751. Area,
  4752. &pSceInfo,
  4753. NULL
  4754. );
  4755. rc = ScepSceStatusToDosError(rc);
  4756. if ( ERROR_SUCCESS != rc ) {
  4757. ScepNotifyLogPolicy(rc, FALSE, L"Error read inf", DbType, ObjectType, TemplateName);
  4758. }
  4759. if ( Area == AREA_ATTACHMENTS ) {
  4760. //
  4761. // now get the real settings for user rights
  4762. //
  4763. Area = AREA_PRIVILEGES;
  4764. if ( pSceInfo ) {
  4765. rc = SceInfpGetPrivileges(
  4766. hProfile.hInf,
  4767. FALSE,
  4768. &(pSceInfo->OtherInfo.smp.pPrivilegeAssignedTo),
  4769. NULL
  4770. );
  4771. rc = ScepSceStatusToDosError(rc);
  4772. if ( ERROR_SUCCESS != rc ) {
  4773. ScepNotifyLogPolicy(rc, FALSE, L"Error read privileges from template", DbType, ObjectType, TemplateName);
  4774. }
  4775. }
  4776. }
  4777. SceInfpCloseProfile(hProfile.hInf);
  4778. } else {
  4779. ScepNotifyLogPolicy(rc, FALSE, L"Error open inf", DbType, ObjectType, TemplateName);
  4780. }
  4781. if ( ERROR_SUCCESS == rc && pSceInfo ) {
  4782. //
  4783. // SMP and INF takes the same structure
  4784. //
  4785. pSceInfo->Type = SCE_ENGINE_SMP;
  4786. BOOL bChanged = FALSE;
  4787. ScepIsDomainLocal(NULL);
  4788. //
  4789. // check if there is difference between current state of LSA
  4790. // and group policy templates.
  4791. //
  4792. rc = ScepNotifyGetChangedPolicies(
  4793. (SECURITY_DB_TYPE)DbType,
  4794. (SECURITY_DB_DELTA_TYPE)DeltaType,
  4795. (SECURITY_DB_OBJECT_TYPE)ObjectType,
  4796. (PSID)ObjectSid,
  4797. pSceInfo,
  4798. NULL,
  4799. FALSE, // not save to DB
  4800. ExplicitLowRight,
  4801. ExplicitHighRight,
  4802. &bChanged
  4803. );
  4804. if ( ERROR_SUCCESS == rc && bChanged ) {
  4805. //
  4806. // no error, get the policy for the area changed
  4807. // now, write it back to the template
  4808. //
  4809. ScepNotifyLogPolicy(0, FALSE, L"Save", DbType, ObjectType, NULL );
  4810. ScepCheckAndWaitPolicyPropFinish();
  4811. PSCE_ERROR_LOG_INFO pErrList=NULL;
  4812. rc = (*pfSceInfWriteInfo)(
  4813. TemplateName,
  4814. Area,
  4815. (PSCE_PROFILE_INFO)pSceInfo,
  4816. &pErrList
  4817. );
  4818. ScepNotifyLogPolicy(rc, FALSE, L"Save operation", DbType, ObjectType, NULL );
  4819. for (PSCE_ERROR_LOG_INFO pErr = pErrList; pErr != NULL; pErr = pErr->next) {
  4820. ScepNotifyLogPolicy(pErr->rc, FALSE, L"Save operation error", DbType, ObjectType, pErr->buffer );
  4821. }
  4822. ScepFreeErrorLog(pErrList);
  4823. rc = ScepSceStatusToDosError(rc);
  4824. //
  4825. // only update version # of the GPO if it's not access denied or file not found
  4826. // if verion # failed to update, still continue but in which case
  4827. // the change will probably not get replicated and applied on
  4828. // other DCs right away
  4829. //
  4830. if ( ERROR_ACCESS_DENIED != rc &&
  4831. ERROR_FILE_NOT_FOUND != rc ) {
  4832. DWORD rc2 = ScepNotifyUpdateGPOVersion( TemplateName,
  4833. bAccountGPO );
  4834. ScepNotifyLogPolicy(rc2, FALSE, L"GPO Version updated", DbType, ObjectType, NULL );
  4835. }
  4836. } else if ( ERROR_SUCCESS == rc ) {
  4837. //
  4838. // nothing changed
  4839. //
  4840. ScepNotifyLogPolicy(0, FALSE, L"No change", DbType, ObjectType, NULL );
  4841. }
  4842. }
  4843. //
  4844. // free any memory allocated
  4845. //
  4846. SceFreeMemory( (PVOID)pSceInfo, Area);
  4847. ScepFree(pSceInfo);
  4848. } else {
  4849. ScepNotifyLogPolicy(rc, FALSE, L"Error get file path", DbType, ObjectType, NULL );
  4850. }
  4851. //
  4852. // free TemplateName
  4853. //
  4854. LocalFree(TemplateName);
  4855. return rc;
  4856. }
  4857. DWORD
  4858. ScepWaitForSynchronizeWithPDC(
  4859. IN UNICODE_STRING DnsDomainName,
  4860. IN PWSTR LocalTemplateName,
  4861. OUT BOOL *pbTimeout
  4862. )
  4863. /*
  4864. Description:
  4865. Wait and verify that local DC is advertised and PDC is available.
  4866. When PDC is available, check the last modified time of local policy
  4867. template is equal or newer than the one on PDC. If the local copy is
  4868. too old, wait and check again until timeout.
  4869. Arguments:
  4870. DnsDomainName - the dns domain name which may be needed in template path
  4871. LocalTemplateName - the template full path name on the local DC.
  4872. pbTimeout - output to indicate if maximum wait has been reached.
  4873. */
  4874. {
  4875. WCHAR SysName[MAX_COMPUTERNAME_LENGTH+1];
  4876. DWORD Len;
  4877. DWORD rc=ERROR_SUCCESS;
  4878. DWORD dwDCWait = 0;
  4879. DWORD dwMaxWaitCount = gdwMaxPDCWait / gdwPDCRetry + 1;
  4880. //
  4881. // make sure current DC is advertised
  4882. //
  4883. PDOMAIN_CONTROLLER_INFOW DCInfo=NULL;
  4884. PDOMAIN_CONTROLLER_INFOW PDCInfo=NULL;
  4885. PWSTR pComputerName=NULL;
  4886. PWSTR pTemp=NULL;
  4887. WIN32_FIND_DATA *LocalFileData=NULL;
  4888. WIN32_FIND_DATA *PDCFileData=NULL;
  4889. LARGE_INTEGER FileTime1;
  4890. LARGE_INTEGER FileTime2;
  4891. HANDLE hLocal=INVALID_HANDLE_VALUE;
  4892. HANDLE hPDC = INVALID_HANDLE_VALUE;
  4893. PWSTR PDCTemplateName=NULL;
  4894. //
  4895. // dynamic allocate stack buffer
  4896. //
  4897. SafeAllocaAllocate(LocalFileData, sizeof(WIN32_FIND_DATA));
  4898. if ( LocalFileData == NULL ) {
  4899. return (ERROR_NOT_ENOUGH_MEMORY);
  4900. }
  4901. SafeAllocaAllocate(PDCFileData, sizeof(WIN32_FIND_DATA));
  4902. if ( PDCFileData == NULL ) {
  4903. SafeAllocaFree(LocalFileData);
  4904. return (ERROR_NOT_ENOUGH_MEMORY);
  4905. }
  4906. do {
  4907. ScepNotifyLogPolicy(0, TRUE, L"Verify Sync: Check synchronization with PDC", 0, 0, NULL );
  4908. SysName[0] = L'\0';
  4909. Len = MAX_COMPUTERNAME_LENGTH;
  4910. if ( !GetComputerName(SysName, &Len) ) {
  4911. rc = GetLastError();
  4912. ScepNotifyLogPolicy(rc, FALSE, L"Verify Sync: Failed to get computer name", 0, 0, NULL );
  4913. //
  4914. // do not return, let it fail in DsGetDcName so we can get the maximum wait
  4915. //
  4916. }
  4917. //
  4918. // get local DC status
  4919. //
  4920. rc = DsGetDcName(SysName,
  4921. NULL,
  4922. NULL,
  4923. NULL,
  4924. DS_IS_DNS_NAME,
  4925. &DCInfo
  4926. );
  4927. if ( ERROR_SUCCESS == rc ) {
  4928. //
  4929. // current DC is available, check the DS role
  4930. // local DC role should be accurate
  4931. //
  4932. if ( 0 == (DCInfo->Flags & DS_PDC_FLAG) ) {
  4933. //
  4934. // local DC is not a PDC, check PDC role
  4935. // get the PDC name first
  4936. //
  4937. rc = DsGetDcName(NULL,
  4938. NULL,
  4939. NULL,
  4940. NULL,
  4941. DS_IS_FLAT_NAME | DS_PDC_REQUIRED,
  4942. &PDCInfo
  4943. );
  4944. if ( ERROR_SUCCESS == rc ) {
  4945. //
  4946. // Even though DsGetDcName tells the DS role is a PDC,
  4947. // it may not be (e.g., FSMO is transferred).
  4948. //
  4949. // Talk to the DC remotely to confirm. If the DC is not
  4950. // hosting a PDC role, let the code wait and retry
  4951. // since DsGetDcName cache will be eventually updated with
  4952. // the correct PDC info
  4953. //
  4954. pComputerName = PDCInfo->DomainControllerName;
  4955. //
  4956. // skip the backslashes
  4957. //
  4958. while ( *pComputerName == L'\\' ) pComputerName++;
  4959. //
  4960. // search for . to extract the computer name
  4961. //
  4962. pTemp = wcschr(pComputerName, L'.');
  4963. if ( pTemp ) *pTemp = L'\0';
  4964. BOOL bIsPDC = TRUE;
  4965. rc = ScepVerifyPDCRole(pComputerName, &bIsPDC);
  4966. //
  4967. // verify that the PDC name returned is indeed a PDC
  4968. //
  4969. if ( ERROR_SUCCESS != rc ) {
  4970. ScepNotifyLogPolicy(rc, FALSE, L"Verify Sync: Fail to verify PDC role for ", 0, 0, pComputerName );
  4971. rc = ERROR_INVALID_DOMAIN_ROLE;
  4972. } else if ( !bIsPDC ) {
  4973. ScepNotifyLogPolicy(0, FALSE, L"Verify Sync: Computer is not really in PDC role.", 0, 0, pComputerName );
  4974. rc = ERROR_INVALID_DOMAIN_ROLE;
  4975. } else {
  4976. //
  4977. // get the timestamp of gpttmpl.inf from the PDC
  4978. //
  4979. PDCTemplateName=NULL;
  4980. rc = ScepNotifyGetDefaultGPOTemplateName(DnsDomainName,
  4981. pComputerName,
  4982. FALSE,
  4983. SCEGPO_NOCHECK_EXISTENCE,
  4984. &PDCTemplateName
  4985. );
  4986. ScepNotifyLogPolicy(rc, FALSE, L"Verify Sync: Get template name on PDC", 0, 0, PDCTemplateName );
  4987. if ( ERROR_SUCCESS != rc ) {
  4988. //
  4989. // if failed to build a template name, it must because of out of memory
  4990. // no need to loop for this kind of failure
  4991. //
  4992. break;
  4993. } else {
  4994. if ( 0xFFFFFFFF == GetFileAttributes(PDCTemplateName) ) {
  4995. //
  4996. // current PDC template is not reachable, try again
  4997. // this could be become of network problem.
  4998. //
  4999. rc = GetLastError();
  5000. ScepNotifyLogPolicy(rc, FALSE, L"Verify Sync: PDC template is not accessible. Try again later", 0, 0, NULL );
  5001. } else {
  5002. //
  5003. // get local timestamp
  5004. //
  5005. memset(LocalFileData, '\0', sizeof(WIN32_FIND_DATA));
  5006. memset(PDCFileData, '\0', sizeof(WIN32_FIND_DATA));
  5007. hLocal=INVALID_HANDLE_VALUE;
  5008. hPDC = INVALID_HANDLE_VALUE;
  5009. hLocal = FindFirstFile(LocalTemplateName, LocalFileData);
  5010. if ( hLocal != INVALID_HANDLE_VALUE ) {
  5011. FindClose(hLocal);
  5012. hLocal = NULL;
  5013. //
  5014. // get PDC time stamp
  5015. //
  5016. hPDC = FindFirstFile(PDCTemplateName, PDCFileData);
  5017. if ( hPDC != INVALID_HANDLE_VALUE ) {
  5018. FindClose(hPDC);
  5019. hPDC = NULL;
  5020. FileTime1.LowPart = LocalFileData->ftLastWriteTime.dwLowDateTime;
  5021. FileTime1.HighPart = LocalFileData->ftLastWriteTime.dwHighDateTime;
  5022. FileTime2.LowPart = PDCFileData->ftLastWriteTime.dwLowDateTime;
  5023. FileTime2.HighPart = PDCFileData->ftLastWriteTime.dwHighDateTime;
  5024. //
  5025. // get time difference in minutes
  5026. //
  5027. LONG lDiff = 0;
  5028. if ( FileTime2.QuadPart != FileTime1.QuadPart ) {
  5029. lDiff = (LONG) ((FileTime2.QuadPart - FileTime1.QuadPart) / 10000000);
  5030. lDiff /= 60;
  5031. if ( lDiff >= 0 ) lDiff ++;
  5032. else lDiff --;
  5033. }
  5034. WCHAR szTime[32];
  5035. swprintf(szTime, L"%d minutes\0", lDiff);
  5036. if ( lDiff <= 0 ) {
  5037. //
  5038. // the local copy is newer or within the allowed delta window
  5039. // so this check is passed
  5040. //
  5041. ScepNotifyLogPolicy(0, FALSE, L"Verify Sync: Local copy is within range from PDC", 0, 0, szTime );
  5042. break;
  5043. } else {
  5044. ScepNotifyLogPolicy(0, FALSE, L"Verify Sync: Local copy is out of range from PDC", 0, 0, szTime );
  5045. rc = WAIT_TIMEOUT;
  5046. }
  5047. } else {
  5048. rc = GetLastError();
  5049. ScepNotifyLogPolicy(rc, FALSE, L"Verify Sync: Failed to get PDC file time", 0, 0, PDCTemplateName );
  5050. }
  5051. } else {
  5052. //
  5053. // if it cannot query file time on the local box
  5054. // something is wrong locally, do not retry
  5055. //
  5056. rc = GetLastError();
  5057. ScepNotifyLogPolicy(rc, FALSE, L"Verify Sync: Failed to get local file time", 0, 0, LocalTemplateName );
  5058. break;
  5059. }
  5060. }
  5061. //
  5062. // mask the error so that caller knows if it reaches maximum wait
  5063. //
  5064. if ( ERROR_SUCCESS != rc ) {
  5065. rc = WAIT_TIMEOUT;
  5066. }
  5067. }
  5068. }
  5069. } else {
  5070. //
  5071. // current PDC is not available, try again
  5072. //
  5073. ScepNotifyLogPolicy(rc, FALSE, L"Verify Sync: Fail to get PDC info. Try again later", 0, 0, NULL );
  5074. rc = ERROR_INVALID_DOMAIN_ROLE;
  5075. }
  5076. } else {
  5077. //
  5078. // local DC is already a PDC, no need to check
  5079. // break the loop
  5080. //
  5081. ScepNotifyLogPolicy(0, FALSE, L"Verify Sync: Local DC is a PDC", 0, 0, NULL );
  5082. break;
  5083. }
  5084. } else {
  5085. ScepNotifyLogPolicy(rc, FALSE, L"Verify Sync: Fail to get local DC info. Try again later", 0, 0, NULL );
  5086. rc = ERROR_DOMAIN_CONTROLLER_NOT_FOUND;
  5087. }
  5088. //
  5089. // restore the name
  5090. //
  5091. if ( pTemp ) {
  5092. *pTemp = L'.';
  5093. pTemp=NULL;
  5094. }
  5095. //
  5096. // free buffers
  5097. //
  5098. if ( PDCInfo ) {
  5099. NetApiBufferFree(PDCInfo);
  5100. PDCInfo = NULL;
  5101. }
  5102. pComputerName = NULL;
  5103. if ( DCInfo ) {
  5104. NetApiBufferFree(DCInfo);
  5105. DCInfo = NULL;
  5106. }
  5107. if ( PDCTemplateName ) {
  5108. ScepFree(PDCTemplateName);
  5109. PDCTemplateName = NULL;
  5110. }
  5111. //
  5112. // sleep for some time and try again
  5113. //
  5114. Sleep(gdwPDCRetry*60*1000);
  5115. dwDCWait++;
  5116. } while ( dwDCWait < dwMaxWaitCount );
  5117. if ( dwDCWait >= dwMaxWaitCount &&
  5118. ERROR_SUCCESS != rc ) {
  5119. //
  5120. // something fails/times out when verifying the PDC, log a message
  5121. //
  5122. switch ( rc ) {
  5123. case ERROR_DOMAIN_CONTROLLER_NOT_FOUND:
  5124. ScepNotifyLogPolicy(0, TRUE, L"Verify Sync: Local DC is not advertised", 0, 0, NULL );
  5125. *pbTimeout = TRUE;
  5126. break;
  5127. case ERROR_INVALID_DOMAIN_ROLE:
  5128. ScepNotifyLogPolicy(0, TRUE, L"Verify Sync: PDC role cannot be found", 0, 0, NULL );
  5129. *pbTimeout = TRUE;
  5130. break;
  5131. case WAIT_TIMEOUT:
  5132. ScepNotifyLogPolicy(0, TRUE, L"Verify Sync: Local policy is not or may not be synchronized with PDC", 0, 0, NULL );
  5133. *pbTimeout = TRUE;
  5134. break;
  5135. }
  5136. }
  5137. //
  5138. // restore the name
  5139. //
  5140. if ( pTemp ) {
  5141. *pTemp = L'.';
  5142. }
  5143. //
  5144. // free buffers
  5145. //
  5146. if ( PDCInfo ) {
  5147. NetApiBufferFree(PDCInfo);
  5148. }
  5149. if ( DCInfo ) {
  5150. NetApiBufferFree(DCInfo);
  5151. }
  5152. if ( PDCTemplateName )
  5153. ScepFree(PDCTemplateName);
  5154. SafeAllocaFree(PDCFileData);
  5155. SafeAllocaFree(LocalFileData);
  5156. return rc;
  5157. }
  5158. DWORD
  5159. ScepVerifyPDCRole(
  5160. IN PWSTR pComputerName,
  5161. OUT BOOL *pbIsPDC
  5162. )
  5163. /*
  5164. Description:
  5165. For the given computer name (returned from DsGetDcName for PDC role),
  5166. verify that it's indeed hold a PDC FSMO at the current time.
  5167. DsGetDcName may returned cached name for the PDC which may not be
  5168. in function, or PDC FSMO may be transferred.
  5169. This is to guarantee that we always compare with PDC policy
  5170. Arguments:
  5171. pComputerName - the computer name for the proposed PDC
  5172. pbIsPDC - When return code is success, TRUE = PDC, FALSE = non PDC
  5173. Return Value:
  5174. Win32 error
  5175. */
  5176. {
  5177. if ( pComputerName == NULL || pbIsPDC == NULL ) {
  5178. return(ERROR_INVALID_PARAMETER);
  5179. }
  5180. NTSTATUS NtStatus;
  5181. LSA_OBJECT_ATTRIBUTES attributes;
  5182. SECURITY_QUALITY_OF_SERVICE service;
  5183. LSA_HANDLE PolicyHandle=NULL;
  5184. DWORD rc=0;
  5185. memset( &attributes, 0, sizeof(attributes) );
  5186. attributes.Length = sizeof(attributes);
  5187. attributes.SecurityQualityOfService = &service;
  5188. service.Length = sizeof(service);
  5189. service.ImpersonationLevel= SecurityImpersonation;
  5190. service.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  5191. service.EffectiveOnly = TRUE;
  5192. LSA_UNICODE_STRING SystemName;
  5193. SystemName.Buffer = pComputerName;
  5194. SystemName.Length = wcslen(pComputerName)*sizeof(WCHAR);
  5195. SystemName.MaximumLength = SystemName.Length + 2;
  5196. //
  5197. // open the remote lsa
  5198. //
  5199. NtStatus = LsaOpenPolicy(
  5200. &SystemName,
  5201. &attributes,
  5202. POLICY_VIEW_LOCAL_INFORMATION,
  5203. &PolicyHandle
  5204. );
  5205. rc = RtlNtStatusToDosError(NtStatus);
  5206. if ( NT_SUCCESS(NtStatus) ) {
  5207. //
  5208. // query LSA server role from the remote computer
  5209. //
  5210. PPOLICY_LSA_SERVER_ROLE_INFO pServerRole=NULL;
  5211. NtStatus = LsaQueryInformationPolicy(PolicyHandle,
  5212. PolicyLsaServerRoleInformation,
  5213. (PVOID *)&pServerRole
  5214. );
  5215. rc = RtlNtStatusToDosError(NtStatus);
  5216. if ( NT_SUCCESS(NtStatus) ) {
  5217. //
  5218. // check the role and set output appropriately
  5219. //
  5220. if ( PolicyServerRolePrimary == pServerRole->LsaServerRole ) {
  5221. *pbIsPDC = TRUE;
  5222. } else {
  5223. *pbIsPDC = FALSE;
  5224. }
  5225. LsaFreeMemory(pServerRole);
  5226. rc = ERROR_SUCCESS;
  5227. }
  5228. LsaClose(PolicyHandle);
  5229. }
  5230. return(rc);
  5231. }
  5232. SCEPR_STATUS
  5233. SceRpcBrowseDatabaseTable(
  5234. IN handle_t binding_h,
  5235. IN wchar_t *DatabaseName OPTIONAL,
  5236. IN SCEPR_TYPE ProfileType,
  5237. IN AREAPR Area,
  5238. IN BOOL bDomainPolicyOnly
  5239. )
  5240. {
  5241. UINT ClientLocalFlag = 0;
  5242. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  5243. 0 == ClientLocalFlag ){
  5244. //
  5245. // to prevent denial-of-service type attacks,
  5246. // do not allow remote RPC
  5247. //
  5248. return SCESTATUS_ACCESS_DENIED;
  5249. }
  5250. SCESTATUS rc;
  5251. if ( bStopRequest ) {
  5252. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  5253. }
  5254. //
  5255. // initialize jet engine in system context
  5256. //
  5257. rc = SceJetInitialize(NULL);
  5258. if ( SCESTATUS_SUCCESS != rc ) {
  5259. return(rc);
  5260. }
  5261. //
  5262. // impersonate the client, return DWORD error code
  5263. //
  5264. rc = RpcImpersonateClient( NULL );
  5265. if (rc != RPC_S_OK) {
  5266. //
  5267. // if no other active clients, terminate jet engine
  5268. //
  5269. ScepIfTerminateEngine();
  5270. return( ScepDosErrorToSceStatus(rc) );
  5271. }
  5272. BOOL bAdminSidInToken = FALSE;
  5273. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  5274. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  5275. RpcRevertToSelf();
  5276. return SCESTATUS_SPECIAL_ACCOUNT;
  5277. }
  5278. //
  5279. // get the database name
  5280. //
  5281. BOOL bAdminLogon=FALSE;
  5282. LPTSTR DefProfile=NULL;
  5283. PSCECONTEXT hProfile=NULL;
  5284. __try {
  5285. rc = ScepGetDefaultDatabase(
  5286. (LPCTSTR)DatabaseName,
  5287. 0,
  5288. NULL,
  5289. &bAdminLogon,
  5290. &DefProfile
  5291. );
  5292. } __except (EXCEPTION_EXECUTE_HANDLER) {
  5293. rc = ERROR_EXCEPTION_IN_SERVICE;
  5294. }
  5295. rc = ScepDosErrorToSceStatus(rc);
  5296. if ( SCESTATUS_SUCCESS == rc && DefProfile ) {
  5297. //
  5298. // OpenDatabase is not blocked by any task.
  5299. //
  5300. EnterCriticalSection(&ContextSync);
  5301. DWORD Option=0;
  5302. if ( ProfileType == SCE_ENGINE_SAP ) {
  5303. if ( bDomainPolicyOnly )
  5304. Option = SCE_OPEN_OPTION_TATTOO;
  5305. else
  5306. Option = SCE_OPEN_OPTION_REQUIRE_ANALYSIS;
  5307. }
  5308. rc = ScepOpenDatabase(
  5309. (PCWSTR)DefProfile,
  5310. Option,
  5311. SCEJET_OPEN_READ_ONLY,
  5312. &hProfile
  5313. );
  5314. if ( SCESTATUS_SUCCESS == rc ) {
  5315. //
  5316. // a new context is opened, add it to the open context list
  5317. //
  5318. if ( (ProfileType != SCE_ENGINE_SAP) && bDomainPolicyOnly &&
  5319. ( (hProfile->Type & 0xF0L) != SCEJET_MERGE_TABLE_1 ) &&
  5320. ( (hProfile->Type & 0xF0L) != SCEJET_MERGE_TABLE_2 ) ) {
  5321. //
  5322. // there is no merged policy table
  5323. //
  5324. rc = SceJetCloseFile(
  5325. hProfile,
  5326. TRUE,
  5327. FALSE
  5328. );
  5329. rc = SCESTATUS_PROFILE_NOT_FOUND;
  5330. hProfile = NULL;
  5331. } else {
  5332. ScepAddToOpenContext(hProfile);
  5333. }
  5334. } else {
  5335. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  5336. SCEDLL_ERROR_OPEN, DefProfile);
  5337. }
  5338. LeaveCriticalSection(&ContextSync);
  5339. if ( DefProfile != DatabaseName )
  5340. ScepFree(DefProfile);
  5341. DefProfile = NULL;
  5342. }
  5343. if ( SCESTATUS_SUCCESS == rc ) {
  5344. if ( ProfileType == SCE_ENGINE_SCP ) {
  5345. switch ( (hProfile->Type & 0xF0L) ) {
  5346. case SCEJET_MERGE_TABLE_1:
  5347. SceClientBrowseCallback(
  5348. 0,
  5349. L"Merged Policy Table 1",
  5350. NULL,
  5351. NULL
  5352. );
  5353. break;
  5354. case SCEJET_MERGE_TABLE_2:
  5355. SceClientBrowseCallback(
  5356. 0,
  5357. L"Merged Policy Table 2",
  5358. NULL,
  5359. NULL
  5360. );
  5361. break;
  5362. default:
  5363. SceClientBrowseCallback(
  5364. 0,
  5365. L"There is no merged policy table. Local policy table is used.",
  5366. NULL,
  5367. NULL
  5368. );
  5369. break;
  5370. }
  5371. }
  5372. //
  5373. // browse the information now
  5374. //
  5375. DWORD dwBrowseOptions;
  5376. if ( (ProfileType != SCE_ENGINE_SAP) && bDomainPolicyOnly ) {
  5377. dwBrowseOptions = SCEBROWSE_DOMAIN_POLICY;
  5378. } else {
  5379. dwBrowseOptions = 0;
  5380. }
  5381. if ( Area & AREA_SECURITY_POLICY ) {
  5382. rc = ScepBrowseTableSection(
  5383. hProfile,
  5384. (SCETYPE)ProfileType,
  5385. szSystemAccess,
  5386. dwBrowseOptions
  5387. );
  5388. if ( SCESTATUS_SUCCESS == rc ) {
  5389. rc = ScepBrowseTableSection(
  5390. hProfile,
  5391. (SCETYPE)ProfileType,
  5392. szKerberosPolicy,
  5393. dwBrowseOptions
  5394. );
  5395. }
  5396. if ( SCESTATUS_SUCCESS == rc ) {
  5397. rc = ScepBrowseTableSection(
  5398. hProfile,
  5399. (SCETYPE)ProfileType,
  5400. szAuditEvent,
  5401. dwBrowseOptions
  5402. );
  5403. }
  5404. if ( SCESTATUS_SUCCESS == rc ) {
  5405. rc = ScepBrowseTableSection(
  5406. hProfile,
  5407. (SCETYPE)ProfileType,
  5408. szAuditSystemLog,
  5409. dwBrowseOptions
  5410. );
  5411. }
  5412. if ( SCESTATUS_SUCCESS == rc ) {
  5413. rc = ScepBrowseTableSection(
  5414. hProfile,
  5415. (SCETYPE)ProfileType,
  5416. szAuditSecurityLog,
  5417. dwBrowseOptions
  5418. );
  5419. }
  5420. if ( SCESTATUS_SUCCESS == rc ) {
  5421. rc = ScepBrowseTableSection(
  5422. hProfile,
  5423. (SCETYPE)ProfileType,
  5424. szAuditApplicationLog,
  5425. dwBrowseOptions
  5426. );
  5427. }
  5428. if ( SCESTATUS_SUCCESS == rc ) {
  5429. rc = ScepBrowseTableSection(
  5430. hProfile,
  5431. (SCETYPE)ProfileType,
  5432. szRegistryValues,
  5433. dwBrowseOptions | SCEBROWSE_MULTI_SZ
  5434. );
  5435. }
  5436. }
  5437. if ( (Area & AREA_PRIVILEGES) &&
  5438. (SCESTATUS_SUCCESS == rc) ) {
  5439. rc = ScepBrowseTableSection(
  5440. hProfile,
  5441. (SCETYPE)ProfileType,
  5442. szPrivilegeRights,
  5443. dwBrowseOptions | SCEBROWSE_MULTI_SZ
  5444. );
  5445. }
  5446. if ( (Area & AREA_GROUP_MEMBERSHIP) &&
  5447. (SCESTATUS_SUCCESS == rc) ) {
  5448. rc = ScepBrowseTableSection(
  5449. hProfile,
  5450. (SCETYPE)ProfileType,
  5451. szGroupMembership,
  5452. dwBrowseOptions | SCEBROWSE_MULTI_SZ
  5453. );
  5454. }
  5455. if ( (Area & AREA_SYSTEM_SERVICE) &&
  5456. (SCESTATUS_SUCCESS == rc) ) {
  5457. rc = ScepBrowseTableSection(
  5458. hProfile,
  5459. (SCETYPE)ProfileType,
  5460. szServiceGeneral,
  5461. dwBrowseOptions
  5462. );
  5463. }
  5464. if ( (Area & AREA_REGISTRY_SECURITY) &&
  5465. (SCESTATUS_SUCCESS == rc) ) {
  5466. rc = ScepBrowseTableSection(
  5467. hProfile,
  5468. (SCETYPE)ProfileType,
  5469. szRegistryKeys,
  5470. dwBrowseOptions
  5471. );
  5472. }
  5473. if ( (Area & AREA_FILE_SECURITY) &&
  5474. (SCESTATUS_SUCCESS == rc) ) {
  5475. rc = ScepBrowseTableSection(
  5476. hProfile,
  5477. (SCETYPE)ProfileType,
  5478. szFileSecurity,
  5479. dwBrowseOptions
  5480. );
  5481. }
  5482. if ( (Area & AREA_ATTACHMENTS) &&
  5483. (SCESTATUS_SUCCESS == rc) ) {
  5484. PSCE_NAME_LIST pList=NULL;
  5485. rc = ScepEnumAttachmentSections( hProfile, &pList);
  5486. if ( rc == SCESTATUS_SUCCESS ) {
  5487. for ( PSCE_NAME_LIST pNode=pList; pNode != NULL; pNode=pNode->Next) {
  5488. rc = ScepBrowseTableSection(
  5489. hProfile,
  5490. (SCETYPE)ProfileType,
  5491. pNode->Name,
  5492. dwBrowseOptions
  5493. );
  5494. if ( SCESTATUS_SUCCESS != rc ) {
  5495. break;
  5496. }
  5497. }
  5498. }
  5499. ScepFreeNameList(pList);
  5500. }
  5501. ScepValidateAndCloseDatabase(hProfile);
  5502. hProfile = NULL;
  5503. } else {
  5504. //
  5505. // start a timer queue to check to see if there is active tasks/contexts
  5506. // if not, terminate jet engine
  5507. //
  5508. ScepIfTerminateEngine();
  5509. }
  5510. ScepLogClose();
  5511. RpcRevertToSelf();
  5512. return((SCEPR_STATUS)rc);
  5513. }
  5514. BOOL
  5515. ScepIsSystemShutDown()
  5516. {
  5517. return(gbSystemShutdown);
  5518. }
  5519. SCESTATUS
  5520. ScepConvertServices(
  5521. IN OUT PVOID *ppServices,
  5522. IN BOOL bSRForm
  5523. )
  5524. {
  5525. if ( !ppServices ) {
  5526. return(SCESTATUS_INVALID_PARAMETER);
  5527. }
  5528. PSCE_SERVICES pTemp = (PSCE_SERVICES)(*ppServices);
  5529. SCESTATUS rc=SCESTATUS_SUCCESS;
  5530. PSCE_SERVICES pNewNode;
  5531. PSCE_SERVICES pNewServices=NULL;
  5532. while ( pTemp ) {
  5533. pNewNode = (PSCE_SERVICES)ScepAlloc(0,sizeof(SCE_SERVICES));
  5534. if ( pNewNode ) {
  5535. pNewNode->ServiceName = pTemp->ServiceName;
  5536. pNewNode->DisplayName = pTemp->DisplayName;
  5537. pNewNode->Status = pTemp->Status;
  5538. pNewNode->Startup = pTemp->Startup;
  5539. pNewNode->SeInfo = pTemp->SeInfo;
  5540. pNewNode->General.pSecurityDescriptor = NULL;
  5541. pNewNode->Next = pNewServices;
  5542. pNewServices = pNewNode;
  5543. if ( bSRForm ) {
  5544. //
  5545. // Service node is in SCEPR_SERVICES structure
  5546. // convert it to SCE_SERVICES structure
  5547. // in this case, just use the self relative security descriptor
  5548. //
  5549. if ( pTemp->General.pSecurityDescriptor) {
  5550. pNewNode->General.pSecurityDescriptor = ((PSCEPR_SERVICES)pTemp)->pSecurityDescriptor->SecurityDescriptor;
  5551. }
  5552. } else {
  5553. //
  5554. // Service node is in SCE_SERVICES strucutre
  5555. // convert it to SCEPR_SERVICES structure
  5556. //
  5557. // make the SD to self relative format and PSCEPR_SR_SECURITY_DESCRIPTOR
  5558. //
  5559. if ( pTemp->General.pSecurityDescriptor ) {
  5560. if ( !RtlValidSid ( pTemp->General.pSecurityDescriptor ) ) {
  5561. rc = SCESTATUS_INVALID_PARAMETER;
  5562. break;
  5563. }
  5564. //
  5565. // get the length
  5566. //
  5567. DWORD nLen = 0;
  5568. DWORD NewLen;
  5569. PSECURITY_DESCRIPTOR pSD;
  5570. PSCEPR_SR_SECURITY_DESCRIPTOR pNewWrap;
  5571. RtlMakeSelfRelativeSD( pTemp->General.pSecurityDescriptor,
  5572. NULL,
  5573. &nLen
  5574. );
  5575. if ( nLen > 0 ) {
  5576. pSD = (PSECURITY_DESCRIPTOR)ScepAlloc(LMEM_ZEROINIT, nLen);
  5577. if ( !pSD ) {
  5578. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  5579. break;
  5580. }
  5581. NewLen = nLen;
  5582. rc = ScepDosErrorToSceStatus(
  5583. RtlNtStatusToDosError(
  5584. RtlMakeSelfRelativeSD( pTemp->General.pSecurityDescriptor,
  5585. pSD,
  5586. &NewLen
  5587. ) ) );
  5588. if ( SCESTATUS_SUCCESS == rc ) {
  5589. //
  5590. // create a wrapper node to contain the security descriptor
  5591. //
  5592. pNewWrap = (PSCEPR_SR_SECURITY_DESCRIPTOR)ScepAlloc(0, sizeof(SCEPR_SR_SECURITY_DESCRIPTOR));
  5593. if ( pNewWrap ) {
  5594. //
  5595. // assign the wrap to the structure
  5596. //
  5597. pNewWrap->SecurityDescriptor = (UCHAR *)pSD;
  5598. pNewWrap->Length = nLen;
  5599. } else {
  5600. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  5601. }
  5602. }
  5603. if ( SCESTATUS_SUCCESS != rc ) {
  5604. ScepFree(pSD);
  5605. break;
  5606. }
  5607. //
  5608. // now link the SR_SD to the list
  5609. //
  5610. ((PSCEPR_SERVICES)pNewNode)->pSecurityDescriptor = pNewWrap;
  5611. } else {
  5612. //
  5613. // something is wrong with the SD
  5614. //
  5615. rc = SCESTATUS_INVALID_PARAMETER;
  5616. break;
  5617. }
  5618. }
  5619. }
  5620. } else {
  5621. //
  5622. // all allocated buffer are in the list of pNewServices
  5623. //
  5624. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  5625. break;
  5626. }
  5627. pTemp = pTemp->Next;
  5628. }
  5629. if ( SCESTATUS_SUCCESS != rc ) {
  5630. //
  5631. // free pNewServices
  5632. //
  5633. ScepFreeConvertedServices( (PVOID)pNewServices, !bSRForm );
  5634. pNewServices = NULL;
  5635. }
  5636. *ppServices = (PVOID)pNewServices;
  5637. return(rc);
  5638. }
  5639. SCESTATUS
  5640. ScepFreeConvertedServices(
  5641. IN PVOID pServices,
  5642. IN BOOL bSRForm
  5643. )
  5644. {
  5645. if ( pServices == NULL ) {
  5646. return(SCESTATUS_SUCCESS);
  5647. }
  5648. PSCEPR_SERVICES pNewNode = (PSCEPR_SERVICES)pServices;
  5649. PSCEPR_SERVICES pTempNode;
  5650. while ( pNewNode ) {
  5651. if ( bSRForm && pNewNode->pSecurityDescriptor ) {
  5652. //
  5653. // free this allocated buffer (PSCEPR_SR_SECURITY_DESCRIPTOR)
  5654. //
  5655. if ( pNewNode->pSecurityDescriptor->SecurityDescriptor ) {
  5656. ScepFree( pNewNode->pSecurityDescriptor->SecurityDescriptor);
  5657. }
  5658. ScepFree(pNewNode->pSecurityDescriptor);
  5659. }
  5660. //
  5661. // also free the PSCEPR_SERVICE node (but not the names referenced by this node)
  5662. //
  5663. pTempNode = pNewNode;
  5664. pNewNode = pNewNode->Next;
  5665. ScepFree(pTempNode);
  5666. }
  5667. return(SCESTATUS_SUCCESS);
  5668. }
  5669. SCESTATUS
  5670. SceRpcGetSystemSecurity(
  5671. IN handle_t binding_h,
  5672. IN AREAPR Area,
  5673. IN DWORD Options,
  5674. OUT PSCEPR_PROFILE_INFO __RPC_FAR *ppInfoBuffer,
  5675. OUT PSCEPR_ERROR_LOG_INFO __RPC_FAR *Errlog OPTIONAL
  5676. )
  5677. /*
  5678. Routine Description:
  5679. Query system security settings)
  5680. Only password, account lockout, kerberos, audit, user rights, and
  5681. SCE registry values are queried.
  5682. multile threads doing get/set system security are not blocked. In
  5683. other words, system security settings are not exclusive.
  5684. */
  5685. {
  5686. UINT ClientLocalFlag = 0;
  5687. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  5688. 0 == ClientLocalFlag ){
  5689. //
  5690. // to prevent denial-of-service type attacks,
  5691. // do not allow remote RPC
  5692. //
  5693. return SCESTATUS_ACCESS_DENIED;
  5694. }
  5695. DWORD rc;
  5696. if ( bStopRequest ) {
  5697. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  5698. }
  5699. //
  5700. // impersonate the client
  5701. //
  5702. rc = RpcImpersonateClient( NULL );
  5703. if (rc != RPC_S_OK) {
  5704. return( rc );
  5705. }
  5706. BOOL bAdminSidInToken = FALSE;
  5707. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  5708. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  5709. RpcRevertToSelf();
  5710. return SCESTATUS_SPECIAL_ACCOUNT;
  5711. }
  5712. __try {
  5713. //
  5714. // catch exception if InfFileName, or pebClient/pdWarning are bogus
  5715. //
  5716. rc = ScepGetSystemSecurity(
  5717. (AREA_INFORMATION)Area,
  5718. Options,
  5719. (PSCE_PROFILE_INFO *)ppInfoBuffer,
  5720. (PSCE_ERROR_LOG_INFO *)Errlog
  5721. );
  5722. } __except(EXCEPTION_EXECUTE_HANDLER) {
  5723. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  5724. }
  5725. RpcRevertToSelf();
  5726. return(rc);
  5727. }
  5728. SCESTATUS
  5729. SceRpcGetSystemSecurityFromHandle(
  5730. IN SCEPR_CONTEXT Context, // must be a context point to system db
  5731. IN AREAPR Area,
  5732. IN DWORD Options,
  5733. OUT PSCEPR_PROFILE_INFO __RPC_FAR *ppInfoBuffer,
  5734. OUT PSCEPR_ERROR_LOG_INFO __RPC_FAR *Errlog OPTIONAL
  5735. )
  5736. /*
  5737. Routine Description:
  5738. Query local security policy from the system (directly)
  5739. Only password, account lockout, kerberos, audit, user rights, and
  5740. SCE registry values are queried.
  5741. multile threads doing get/set system security are not blocked. In
  5742. other words, system security settings are not exclusive.
  5743. */
  5744. {
  5745. UINT ClientLocalFlag = 0;
  5746. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  5747. 0 == ClientLocalFlag ){
  5748. //
  5749. // to prevent denial-of-service type attacks,
  5750. // do not allow remote RPC
  5751. //
  5752. return SCESTATUS_ACCESS_DENIED;
  5753. }
  5754. DWORD rc;
  5755. if ( bStopRequest ) {
  5756. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  5757. }
  5758. //
  5759. // should we validate the profile handle?
  5760. // it's not used here so it's not validated now.
  5761. //
  5762. //
  5763. // impersonate the client
  5764. //
  5765. rc = RpcImpersonateClient( NULL );
  5766. if (rc != RPC_S_OK) {
  5767. return( rc );
  5768. }
  5769. BOOL bAdminSidInToken = FALSE;
  5770. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  5771. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  5772. RpcRevertToSelf();
  5773. return SCESTATUS_SPECIAL_ACCOUNT;
  5774. }
  5775. __try {
  5776. //
  5777. // catch exception if InfFileName, or pebClient/pdWarning are bogus
  5778. //
  5779. rc = ScepGetSystemSecurity(
  5780. (AREA_INFORMATION)Area,
  5781. Options,
  5782. (PSCE_PROFILE_INFO *)ppInfoBuffer,
  5783. (PSCE_ERROR_LOG_INFO *)Errlog
  5784. );
  5785. } __except(EXCEPTION_EXECUTE_HANDLER) {
  5786. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  5787. }
  5788. RpcRevertToSelf();
  5789. return(rc);
  5790. }
  5791. SCEPR_STATUS
  5792. SceRpcSetSystemSecurityFromHandle(
  5793. IN SCEPR_CONTEXT Context, // must be a context point to system db
  5794. IN AREAPR Area,
  5795. IN DWORD Options,
  5796. IN PSCEPR_PROFILE_INFO __RPC_FAR pInfoBuffer,
  5797. OUT PSCEPR_ERROR_LOG_INFO __RPC_FAR *Errlog OPTIONAL
  5798. )
  5799. /*
  5800. Routine Description:
  5801. Set local security policy to the system (directly)
  5802. Only password, account lockout, kerberos, audit, user rights, and
  5803. SCE registry values are set.
  5804. */
  5805. {
  5806. UINT ClientLocalFlag = 0;
  5807. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  5808. 0 == ClientLocalFlag ){
  5809. //
  5810. // to prevent denial-of-service type attacks,
  5811. // do not allow remote RPC
  5812. //
  5813. return SCESTATUS_ACCESS_DENIED;
  5814. }
  5815. DWORD rc;
  5816. if ( bStopRequest ) {
  5817. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  5818. }
  5819. //
  5820. // should we validate the profile handle?
  5821. // it's not used here so it's not validated now.
  5822. //
  5823. //
  5824. // impersonate the client
  5825. //
  5826. rc = RpcImpersonateClient( NULL );
  5827. if (rc != RPC_S_OK) {
  5828. return( rc );
  5829. }
  5830. BOOL bAdminSidInToken = FALSE;
  5831. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  5832. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  5833. RpcRevertToSelf();
  5834. return SCESTATUS_SPECIAL_ACCOUNT;
  5835. }
  5836. __try {
  5837. //
  5838. // catch exception if InfFileName, or pebClient/pdWarning are bogus
  5839. //
  5840. rc = ScepSetSystemSecurity(
  5841. (AREA_INFORMATION)Area,
  5842. Options,
  5843. (PSCE_PROFILE_INFO)pInfoBuffer,
  5844. (PSCE_ERROR_LOG_INFO *)Errlog
  5845. );
  5846. } __except(EXCEPTION_EXECUTE_HANDLER) {
  5847. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  5848. }
  5849. RpcRevertToSelf();
  5850. return(rc);
  5851. }
  5852. SCEPR_STATUS
  5853. SceRpcSetSystemSecurity(
  5854. IN handle_t binding_h,
  5855. IN AREAPR Area,
  5856. IN DWORD Options,
  5857. IN PSCEPR_PROFILE_INFO __RPC_FAR pInfoBuffer,
  5858. OUT PSCEPR_ERROR_LOG_INFO __RPC_FAR *Errlog OPTIONAL
  5859. )
  5860. /*
  5861. Routine Description:
  5862. Set local security policy to the system (directly)
  5863. Only password, account lockout, kerberos, audit, user rights, and
  5864. SCE registry values are set.
  5865. */
  5866. {
  5867. UINT ClientLocalFlag = 0;
  5868. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  5869. 0 == ClientLocalFlag ){
  5870. //
  5871. // to prevent denial-of-service type attacks,
  5872. // do not allow remote RPC
  5873. //
  5874. return SCESTATUS_ACCESS_DENIED;
  5875. }
  5876. DWORD rc;
  5877. if ( bStopRequest ) {
  5878. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  5879. }
  5880. //
  5881. // impersonate the client
  5882. //
  5883. rc = RpcImpersonateClient( NULL );
  5884. if (rc != RPC_S_OK) {
  5885. return( rc );
  5886. }
  5887. BOOL bAdminSidInToken = FALSE;
  5888. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  5889. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  5890. RpcRevertToSelf();
  5891. return SCESTATUS_SPECIAL_ACCOUNT;
  5892. }
  5893. __try {
  5894. //
  5895. // catch exception if InfFileName, or pebClient/pdWarning are bogus
  5896. //
  5897. rc = ScepSetSystemSecurity(
  5898. (AREA_INFORMATION)Area,
  5899. Options,
  5900. (PSCE_PROFILE_INFO)pInfoBuffer,
  5901. (PSCE_ERROR_LOG_INFO *)Errlog
  5902. );
  5903. } __except(EXCEPTION_EXECUTE_HANDLER) {
  5904. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  5905. }
  5906. RpcRevertToSelf();
  5907. return(rc);
  5908. }
  5909. SCEPR_STATUS
  5910. SceRpcSetDatabaseSetting(
  5911. IN SCEPR_CONTEXT Context,
  5912. IN SCEPR_TYPE ProfileType,
  5913. IN wchar_t *SectionName,
  5914. IN wchar_t *KeyName,
  5915. IN PSCEPR_VALUEINFO pValueInfo OPTIONAL
  5916. )
  5917. /*
  5918. Set or delete value from the given key
  5919. if pValueInfo is NULL, delete the key
  5920. */
  5921. {
  5922. UINT ClientLocalFlag = 0;
  5923. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  5924. 0 == ClientLocalFlag ){
  5925. //
  5926. // to prevent denial-of-service type attacks,
  5927. // do not allow remote RPC
  5928. //
  5929. return SCESTATUS_ACCESS_DENIED;
  5930. }
  5931. if ( SCEPR_SMP != ProfileType ) {
  5932. return SCESTATUS_INVALID_PARAMETER;
  5933. }
  5934. SCESTATUS rc;
  5935. //
  5936. // impersonate the client
  5937. //
  5938. rc = RpcImpersonateClient( NULL );
  5939. if (rc != RPC_S_OK) {
  5940. return( ScepDosErrorToSceStatus(rc) );
  5941. }
  5942. BOOL bAdminSidInToken = FALSE;
  5943. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  5944. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  5945. RpcRevertToSelf();
  5946. return SCESTATUS_SPECIAL_ACCOUNT;
  5947. }
  5948. //
  5949. // validate the context handle is a SCE context
  5950. // Only one database operation per context
  5951. //
  5952. PSCESRV_DBTASK pTask=NULL;
  5953. PSCESECTION hSection=NULL;
  5954. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  5955. SCE_TASK_LOCK,
  5956. FALSE,
  5957. &pTask);
  5958. if (SCESTATUS_SUCCESS == rc ) {
  5959. //
  5960. // lock the context
  5961. //
  5962. if ( pTask ) {
  5963. EnterCriticalSection(&(pTask->Sync));
  5964. }
  5965. __try {
  5966. //
  5967. // catch exception if Context, ppInfoBuffer, Errlog are bogus pointers
  5968. //
  5969. #ifdef SCE_JET_TRAN
  5970. rc = SceJetJetErrorToSceStatus(
  5971. JetSetSessionContext(
  5972. ((PSCECONTEXT)Context)->JetSessionID,
  5973. (ULONG_PTR)Context
  5974. ));
  5975. if ( SCESTATUS_SUCCESS == rc ) {
  5976. #endif
  5977. //
  5978. // query the information now
  5979. //
  5980. rc = ScepOpenSectionForName(
  5981. (PSCECONTEXT)Context,
  5982. (SCETYPE)ProfileType,
  5983. SectionName,
  5984. &hSection
  5985. );
  5986. if ( SCESTATUS_SUCCESS == rc ) {
  5987. if ( pValueInfo == NULL || pValueInfo->Value == NULL ) {
  5988. // delete the key
  5989. rc = SceJetDelete(
  5990. hSection,
  5991. KeyName,
  5992. FALSE,
  5993. SCEJET_DELETE_LINE_NO_CASE
  5994. );
  5995. } else {
  5996. // set the value
  5997. rc = SceJetSetLine(
  5998. hSection,
  5999. KeyName,
  6000. FALSE,
  6001. (PWSTR)pValueInfo->Value,
  6002. pValueInfo->ValueLen,
  6003. 0
  6004. );
  6005. }
  6006. SceJetCloseSection(&hSection, TRUE);
  6007. }
  6008. #ifdef SCE_JET_TRAN
  6009. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  6010. }
  6011. #endif
  6012. } __except(EXCEPTION_EXECUTE_HANDLER) {
  6013. //
  6014. // free ppInfoBuffer if it's allocated
  6015. //
  6016. if ( hSection )
  6017. SceJetCloseSection(&hSection, TRUE);
  6018. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  6019. }
  6020. //
  6021. // unlock the context
  6022. //
  6023. if ( pTask ) {
  6024. LeaveCriticalSection(&(pTask->Sync));
  6025. }
  6026. //
  6027. // remove the context from task table
  6028. //
  6029. ScepRemoveTask(pTask);
  6030. }
  6031. RpcRevertToSelf();
  6032. return((SCEPR_STATUS)rc);
  6033. }
  6034. SCEPR_STATUS
  6035. SceRpcGetDatabaseSetting(
  6036. IN SCEPR_CONTEXT Context,
  6037. IN SCEPR_TYPE ProfileType,
  6038. IN wchar_t *SectionName,
  6039. IN wchar_t *KeyName,
  6040. OUT PSCEPR_VALUEINFO *pValueInfo
  6041. )
  6042. /*
  6043. Routine Description:
  6044. Get information for the particular key from the context database.
  6045. Arguments:
  6046. Return Value:
  6047. */
  6048. {
  6049. UINT ClientLocalFlag = 0;
  6050. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  6051. 0 == ClientLocalFlag ){
  6052. //
  6053. // to prevent denial-of-service type attacks,
  6054. // do not allow remote RPC
  6055. //
  6056. return SCESTATUS_ACCESS_DENIED;
  6057. }
  6058. if ( !pValueInfo ) {
  6059. return(SCESTATUS_INVALID_PARAMETER);
  6060. }
  6061. if ( SCEPR_SMP != ProfileType ) {
  6062. return SCESTATUS_INVALID_PARAMETER;
  6063. }
  6064. SCESTATUS rc;
  6065. //
  6066. // impersonate the client
  6067. //
  6068. rc = RpcImpersonateClient( NULL );
  6069. if (rc != RPC_S_OK) {
  6070. return( ScepDosErrorToSceStatus(rc) );
  6071. }
  6072. BOOL bAdminSidInToken = FALSE;
  6073. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  6074. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  6075. RpcRevertToSelf();
  6076. return SCESTATUS_SPECIAL_ACCOUNT;
  6077. }
  6078. //
  6079. // validate the context handle is a SCE context
  6080. // Only one database operation per context
  6081. //
  6082. PSCESRV_DBTASK pTask=NULL;
  6083. PSCESECTION hSection=NULL;
  6084. PWSTR Value=NULL;
  6085. rc = ScepValidateAndLockContext((PSCECONTEXT)Context,
  6086. SCE_TASK_LOCK,
  6087. FALSE,
  6088. &pTask);
  6089. if (SCESTATUS_SUCCESS == rc ) {
  6090. //
  6091. // lock the context
  6092. //
  6093. if ( pTask ) {
  6094. EnterCriticalSection(&(pTask->Sync));
  6095. }
  6096. __try {
  6097. //
  6098. // catch exception if Context, ppInfoBuffer, Errlog are bogus pointers
  6099. //
  6100. #ifdef SCE_JET_TRAN
  6101. rc = SceJetJetErrorToSceStatus(
  6102. JetSetSessionContext(
  6103. ((PSCECONTEXT)Context)->JetSessionID,
  6104. (ULONG_PTR)Context
  6105. ));
  6106. if ( SCESTATUS_SUCCESS == rc ) {
  6107. #endif
  6108. //
  6109. // query the information now
  6110. //
  6111. rc = ScepOpenSectionForName(
  6112. (PSCECONTEXT)Context,
  6113. (SCETYPE)ProfileType,
  6114. SectionName,
  6115. &hSection
  6116. );
  6117. if ( SCESTATUS_SUCCESS == rc ) {
  6118. DWORD ValueLen=0;
  6119. DWORD NewLen=0;
  6120. rc = SceJetGetValue(
  6121. hSection,
  6122. SCEJET_EXACT_MATCH_NO_CASE,
  6123. KeyName,
  6124. NULL,
  6125. 0,
  6126. NULL,
  6127. NULL,
  6128. 0,
  6129. &ValueLen
  6130. );
  6131. // allocate output buffer
  6132. if ( SCESTATUS_SUCCESS == rc ) {
  6133. Value = (PWSTR)ScepAlloc(LPTR, ValueLen+2);
  6134. if ( !Value )
  6135. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  6136. else {
  6137. *pValueInfo = (PSCEPR_VALUEINFO)ScepAlloc(0,sizeof(SCEPR_VALUEINFO));
  6138. if ( *pValueInfo == NULL ) {
  6139. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  6140. }
  6141. }
  6142. }
  6143. // query the value
  6144. if ( SCESTATUS_SUCCESS == rc ) {
  6145. rc = SceJetGetValue(
  6146. hSection,
  6147. SCEJET_CURRENT,
  6148. KeyName,
  6149. NULL,
  6150. 0,
  6151. NULL,
  6152. Value,
  6153. ValueLen,
  6154. &NewLen
  6155. );
  6156. if ( SCESTATUS_SUCCESS == rc ) {
  6157. (*pValueInfo)->ValueLen = ValueLen+2;
  6158. (*pValueInfo)->Value = (byte *)Value;
  6159. }
  6160. }
  6161. // free buffer
  6162. if ( SCESTATUS_SUCCESS != rc ) {
  6163. if ( Value ) ScepFree(Value);
  6164. if ( *pValueInfo ) {
  6165. ScepFree(*pValueInfo);
  6166. *pValueInfo = NULL;
  6167. }
  6168. }
  6169. SceJetCloseSection(&hSection, TRUE);
  6170. }
  6171. #ifdef SCE_JET_TRAN
  6172. JetResetSessionContext(((PSCECONTEXT)Context)->JetSessionID);
  6173. }
  6174. #endif
  6175. } __except(EXCEPTION_EXECUTE_HANDLER) {
  6176. //
  6177. // free ppInfoBuffer if it's allocated
  6178. //
  6179. if ( Value ) ScepFree(Value);
  6180. if ( *pValueInfo ) {
  6181. ScepFree(*pValueInfo);
  6182. *pValueInfo = NULL;
  6183. }
  6184. if ( hSection )
  6185. SceJetCloseSection(&hSection, TRUE);
  6186. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  6187. }
  6188. //
  6189. // unlock the context
  6190. //
  6191. if ( pTask ) {
  6192. LeaveCriticalSection(&(pTask->Sync));
  6193. }
  6194. //
  6195. // remove the context from task table
  6196. //
  6197. ScepRemoveTask(pTask);
  6198. }
  6199. RpcRevertToSelf();
  6200. return((SCEPR_STATUS)rc);
  6201. }
  6202. DWORD
  6203. SceRpcConfigureConvertedFileSecurityImmediately(
  6204. IN handle_t binding_h,
  6205. IN wchar_t *pszDriveName
  6206. )
  6207. /*
  6208. Routine Description:
  6209. RPC interface called by SCE client (only when conversion of security is immediate)
  6210. Arguments:
  6211. binding_h - binding handle
  6212. pszDriveName - name of the volume for which setup-style security is to be applied
  6213. Return:
  6214. win32 error code
  6215. */
  6216. {
  6217. UINT ClientLocalFlag = 0;
  6218. if ( RPC_S_OK != I_RpcBindingIsClientLocal( NULL, &ClientLocalFlag) ||
  6219. 0 == ClientLocalFlag ){
  6220. //
  6221. // to prevent denial-of-service type attacks,
  6222. // do not allow remote RPC
  6223. //
  6224. return SCESTATUS_ACCESS_DENIED;
  6225. }
  6226. DWORD rc = ERROR_SUCCESS;
  6227. NTSTATUS Status = NO_ERROR;
  6228. if ( pszDriveName == NULL ) {
  6229. return ERROR_INVALID_PARAMETER;
  6230. }
  6231. //
  6232. // impersonate the client
  6233. //
  6234. rc = RpcImpersonateClient( NULL );
  6235. if (rc != RPC_S_OK) {
  6236. return( rc );
  6237. }
  6238. BOOL bAdminSidInToken = FALSE;
  6239. rc = ScepDosErrorToSceStatus(ScepIsAdminLoggedOn(&bAdminSidInToken, TRUE));
  6240. if (SCESTATUS_SUCCESS != rc || FALSE == bAdminSidInToken) {
  6241. RpcRevertToSelf();
  6242. return SCESTATUS_SPECIAL_ACCOUNT;
  6243. }
  6244. rc = ScepConfigureConvertedFileSecurityImmediate( pszDriveName );
  6245. RpcRevertToSelf();
  6246. return(rc);
  6247. }
  6248. DWORD
  6249. ScepServerConfigureSystem(
  6250. IN PWSTR InfFileName,
  6251. IN PWSTR DatabaseName,
  6252. IN PWSTR LogFileName,
  6253. IN DWORD ConfigOptions,
  6254. IN AREA_INFORMATION Area
  6255. )
  6256. /*
  6257. Routine Description:
  6258. Configure the system using the Inf template. This routine is similar to the RPC interface
  6259. SceRpcConfigureSystem except that the configuration is initiated by the server itself.
  6260. Since this routine is called by the server only (system context) and not by sce client,
  6261. there is no need to do impersonate etc.
  6262. Log file initialization etc. is done outside of this routine
  6263. Arguments:
  6264. InfFileName - name of inf file to import configuration information from
  6265. DatabaseName - name of database to import into
  6266. LogFileName - name of log file to log errors
  6267. ConfigOptions - configuration options ()
  6268. Area - security area to configure
  6269. Return Value:
  6270. win32 error code
  6271. */
  6272. {
  6273. DWORD rc = ERROR_SUCCESS;
  6274. if (InfFileName == NULL || DatabaseName == NULL || LogFileName == NULL)
  6275. return ERROR_INVALID_PARAMETER;
  6276. //
  6277. // initialize jet engine in system context if not already initialized
  6278. //
  6279. rc = SceJetInitialize(NULL);
  6280. if ( rc != SCESTATUS_SUCCESS ) {
  6281. return(ScepSceStatusToDosError(rc));
  6282. }
  6283. //
  6284. // no one else can use convert.sdb - lock access to it
  6285. //
  6286. rc = ScepLockEngine(DatabaseName);
  6287. if ( SCESTATUS_ALREADY_RUNNING == rc ) {
  6288. //
  6289. // will wait for max one minute
  6290. //
  6291. DWORD dwWaitCount = 0;
  6292. while ( TRUE ) {
  6293. Sleep(5000); // 5 seconds
  6294. rc = ScepLockEngine(DatabaseName);
  6295. dwWaitCount++;
  6296. if ( SCESTATUS_SUCCESS == rc ||
  6297. dwWaitCount >= 12 ) {
  6298. break;
  6299. }
  6300. }
  6301. }
  6302. if ( SCESTATUS_SUCCESS == rc ) {
  6303. __try {
  6304. //
  6305. // catch exception if InfFileName, or pebClient/pdWarning are bogus
  6306. //
  6307. rc = ScepConfigureSystem(
  6308. (LPCTSTR)InfFileName,
  6309. DatabaseName,
  6310. ConfigOptions,
  6311. TRUE,
  6312. (AREA_INFORMATION)Area,
  6313. NULL
  6314. );
  6315. } __except(EXCEPTION_EXECUTE_HANDLER) {
  6316. rc = SCESTATUS_EXCEPTION_IN_SERVER;
  6317. }
  6318. ScepUnlockEngine(DatabaseName);
  6319. }
  6320. //
  6321. // start a timer queue to check to see if there is active tasks/contexts
  6322. // if not, terminate jet engine
  6323. //
  6324. ScepIfTerminateEngine();
  6325. return(ScepSceStatusToDosError(rc));
  6326. }