Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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