Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

780 lines
22 KiB

  1. /******************************************************************************
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. erswait.cpp
  5. Abstract:
  6. Implementation of DLL Exports.
  7. Revision History:
  8. derekm 02/28/2001 created
  9. ******************************************************************************/
  10. #include "stdafx.h"
  11. #include "stdio.h"
  12. #include "pfrcfg.h"
  13. //////////////////////////////////////////////////////////////////////////////
  14. // Globals
  15. SECURITY_DESCRIPTOR g_rgsd[ertiCount];
  16. SRequestEventType g_rgEvents[ertiCount];
  17. HANDLE g_hmutUser = NULL;
  18. HANDLE g_hmutKrnl = NULL;
  19. HANDLE g_hmutShut = NULL;
  20. //////////////////////////////////////////////////////////////////////////////
  21. // misc stuff
  22. // ***************************************************************************
  23. void InitializeSvcDataStructs(void)
  24. {
  25. ZeroMemory(g_rgsd, ertiCount * sizeof(SECURITY_DESCRIPTOR));
  26. ZeroMemory(g_rgEvents, ertiCount * sizeof(SRequestEventType));
  27. g_rgEvents[ertiHang].pfn = ProcessHangRequest;
  28. g_rgEvents[ertiHang].wszPipeName = c_wszHangPipe;
  29. g_rgEvents[ertiHang].wszRVPipeCount = c_wszRVNumHangPipe;
  30. g_rgEvents[ertiHang].cPipes = c_cMinPipes;
  31. g_rgEvents[ertiHang].fAllowNonLS = FALSE;
  32. g_rgEvents[ertiFault].pfn = ProcessFaultRequest;
  33. g_rgEvents[ertiFault].wszPipeName = c_wszFaultPipe;
  34. g_rgEvents[ertiFault].wszRVPipeCount = c_wszRVNumFaultPipe;
  35. g_rgEvents[ertiFault].cPipes = c_cMinPipes;
  36. g_rgEvents[ertiFault].fAllowNonLS = TRUE;
  37. }
  38. //////////////////////////////////////////////////////////////////////////////
  39. // pipe manager
  40. // ***************************************************************************
  41. BOOL ExecServer(SRequest *pReq)
  42. {
  43. OVERLAPPED ol;
  44. HANDLE rghWait[2] = { NULL, NULL };
  45. HANDLE hPipe = INVALID_HANDLE_VALUE;
  46. DWORD cbBuf, cb, dw;
  47. BOOL fRet, fShutdown = FALSE;
  48. BYTE Buf[ERRORREP_PIPE_BUF_SIZE];
  49. rghWait[0] = g_hevSvcStop;
  50. hPipe = pReq->hPipe;
  51. if (hPipe == INVALID_HANDLE_VALUE || rghWait[0] == NULL ||
  52. pReq->pret->pfn == NULL)
  53. {
  54. SetLastError(ERROR_INVALID_PARAMETER);
  55. goto done;
  56. }
  57. // need another event for waiting on the pipe read
  58. rghWait[1] = CreateEventW(NULL, TRUE, FALSE, NULL);
  59. if (rghWait[1] == NULL)
  60. goto done;
  61. // setup the overlapped structure
  62. ZeroMemory(&ol, sizeof(ol));
  63. ol.hEvent = rghWait[1];
  64. // read the request
  65. ResetEvent(ol.hEvent);
  66. fRet = ReadFile(hPipe, Buf, sizeof(Buf), &cb, &ol);
  67. if (fRet == FALSE && GetLastError() == ERROR_IO_PENDING)
  68. {
  69. // give the client 60s to write the data to us.
  70. // WAIT_OBJECT_0 is the shutdown event
  71. // WAIT_OBJECT_0 + 1 is the overlapped event
  72. dw = WaitForMultipleObjects(2, rghWait, FALSE, 60000);
  73. if (dw == WAIT_OBJECT_0)
  74. fShutdown = TRUE;
  75. else if (dw != WAIT_OBJECT_0 + 1)
  76. goto done;
  77. fRet = TRUE;
  78. }
  79. if (fRet)
  80. fRet = GetOverlappedResult(hPipe, &ol, &cbBuf, FALSE);
  81. // if we got an error, the client might still be waiting for a
  82. // reply, so construct a default one.
  83. // ProcessExecRequest() will always construct a reply and store it
  84. // in Buf, so no special handling is needed if it fails.
  85. if (fShutdown == FALSE && fRet)
  86. {
  87. cbBuf = sizeof(Buf);
  88. fRet = (*(pReq->pret->pfn))(hPipe, Buf, &cbBuf);
  89. }
  90. else
  91. {
  92. SPCHExecServGenericReply esrep;
  93. ZeroMemory(&esrep, sizeof(esrep));
  94. esrep.cb = sizeof(esrep);
  95. esrep.ess = essErr;
  96. esrep.dwErr = GetLastError();
  97. RtlCopyMemory(Buf, &esrep, sizeof(esrep));
  98. cbBuf = sizeof(esrep);
  99. }
  100. // write the reply to the message
  101. ResetEvent(ol.hEvent);
  102. fRet = WriteFile(hPipe, Buf, cbBuf, &cb, &ol);
  103. if (fRet == FALSE && GetLastError() == ERROR_IO_PENDING)
  104. {
  105. // give ourselves 60s to write the data to the pipe.
  106. // WAIT_OBJECT_0 is the shutdown event
  107. // WAIT_OBJECT_0 + 1 is the overlapped event
  108. dw = WaitForMultipleObjects(2, rghWait, FALSE, 60000);
  109. if (dw == WAIT_OBJECT_0)
  110. fShutdown = TRUE;
  111. else if (dw != WAIT_OBJECT_0 + 1)
  112. goto done;
  113. fRet = TRUE;
  114. }
  115. // wait for the client to read the buffer- note that we could use
  116. // FlushFileBuffers() to do this, but that is blocking with no
  117. // timeout, so we try to do a read on the pipe & wait to get an
  118. // error indicating that the client closed it.
  119. // Yup, this is a hack, but this is apparently the way to do this
  120. // when using async pipe communication. Sigh...
  121. if (fShutdown == FALSE && fRet)
  122. {
  123. ResetEvent(ol.hEvent);
  124. fRet = ReadFile(hPipe, Buf, sizeof(Buf), &cb, &ol);
  125. if (fRet == FALSE && GetLastError() == ERROR_IO_PENDING)
  126. {
  127. // give ourselves 60s to read the data from the pipe.
  128. // Except for the shutdown notification, don't really
  129. // care what this routine returns cuz we're just using
  130. // it to wait on the read to finish
  131. // WAIT_OBJECT_0 is the shutdown event
  132. // WAIT_OBJECT_0 + 1 is the overlapped event
  133. dw = WaitForMultipleObjects(2, rghWait, FALSE, 60000);
  134. if (dw == WAIT_OBJECT_0)
  135. fShutdown = TRUE;
  136. }
  137. }
  138. SetLastError(0);
  139. done:
  140. dw = GetLastError();
  141. if (hPipe != INVALID_HANDLE_VALUE)
  142. DisconnectNamedPipe(hPipe);
  143. if (rghWait[1] != NULL)
  144. CloseHandle(rghWait[1]);
  145. SetLastError(dw);
  146. return fShutdown;
  147. }
  148. // ***************************************************************************
  149. DWORD WINAPI threadExecServer(PVOID pvContext)
  150. {
  151. SRequest *pReq = (SRequest *)pvContext;
  152. if (pReq == NULL)
  153. {
  154. // if (pReq->hModErsvc) FreeLibrary(pReq->hModErsvc);
  155. return ERROR_INVALID_PARAMETER;
  156. }
  157. // this acquires the request CS and holds it until the function exits
  158. CAutoUnlockCS aucs(&pReq->csReq, TRUE);
  159. // make sure we aren't shutting down
  160. if (WaitForSingleObject(g_hevSvcStop, 0) != WAIT_TIMEOUT)
  161. {
  162. SetLastError( ERROR_SUCCESS );
  163. goto done;
  164. }
  165. __try { ExecServer(pReq); }
  166. __except(SetLastError(GetExceptionCode()), EXCEPTION_EXECUTE_HANDLER) { }
  167. done:
  168. if (pReq->hModErsvc) FreeLibrary(pReq->hModErsvc);
  169. return GetLastError();
  170. }
  171. //////////////////////////////////////////////////////////////////////////////
  172. // object manager
  173. // ***************************************************************************
  174. void NukeRequestObj(SRequest *pReq, BOOL fFreeEvent)
  175. {
  176. if (pReq == NULL)
  177. return;
  178. // this acquires the request CS and holds it until the function exits
  179. CAutoUnlockCS aucs(&pReq->csReq, TRUE);
  180. // free the pipe
  181. if (pReq->hPipe != INVALID_HANDLE_VALUE)
  182. {
  183. DisconnectNamedPipe(pReq->hPipe);
  184. CloseHandle(pReq->hPipe);
  185. pReq->hPipe = INVALID_HANDLE_VALUE;
  186. }
  187. if (fFreeEvent && pReq->ol.hEvent != NULL)
  188. {
  189. CloseHandle(pReq->ol.hEvent);
  190. ZeroMemory(&pReq->ol, sizeof(pReq->ol));
  191. }
  192. if (pReq->hth != NULL)
  193. {
  194. CloseHandle(pReq->hth);
  195. pReq->hth = NULL;
  196. }
  197. pReq->ers = ersEmpty;
  198. }
  199. // ***************************************************************************
  200. BOOL BuildRequestObj(SRequest *pReq, SRequestEventType *pret)
  201. {
  202. SECURITY_ATTRIBUTES sa;
  203. HANDLE hev = NULL;
  204. HANDLE hPipe = INVALID_HANDLE_VALUE;
  205. BOOL fRet = FALSE;
  206. if (pReq == NULL || pret == NULL)
  207. {
  208. SetLastError(ERROR_INVALID_PARAMETER);
  209. goto done;
  210. }
  211. // if this is empty, then we're building a fresh object, so create an
  212. // event for waiting on the pipe listen
  213. if (pReq->ol.hEvent == NULL)
  214. {
  215. // need an
  216. hev = CreateEventW(NULL, FALSE, FALSE, NULL);
  217. if (hev == NULL)
  218. goto done;
  219. }
  220. // otherwise, store away the existing event
  221. else
  222. {
  223. hev = pReq->ol.hEvent;
  224. ResetEvent(hev);
  225. }
  226. // don't want to nuke the critical section!
  227. ZeroMemory(((PBYTE)pReq + sizeof(pReq->csReq)),
  228. sizeof(SRequest) - sizeof(pReq->csReq));
  229. sa.nLength = sizeof(sa);
  230. sa.bInheritHandle = FALSE;
  231. sa.lpSecurityDescriptor = pret->psd;
  232. // obviously gotta have a pipe
  233. hPipe = CreateNamedPipeW(pret->wszPipeName,
  234. PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
  235. PIPE_WAIT | PIPE_READMODE_MESSAGE | PIPE_TYPE_MESSAGE,
  236. c_cMaxPipes, ERRORREP_PIPE_BUF_SIZE,
  237. ERRORREP_PIPE_BUF_SIZE, 0, &sa);
  238. if (hPipe == INVALID_HANDLE_VALUE)
  239. goto done;
  240. // make sure we aren't shutting down
  241. if (WaitForSingleObject(g_hevSvcStop, 0) != WAIT_TIMEOUT)
  242. goto done;
  243. pReq->ol.hEvent = hev;
  244. // start waiting on the pipe
  245. fRet = ConnectNamedPipe(hPipe, &pReq->ol);
  246. if (fRet == FALSE && GetLastError() != ERROR_IO_PENDING)
  247. {
  248. // if the pipe is already connected, just set the event cuz
  249. // ConnectNamedPipe doesn't
  250. if (GetLastError() == ERROR_PIPE_CONNECTED)
  251. {
  252. SetEvent(pReq->ol.hEvent);
  253. }
  254. else
  255. {
  256. pReq->ol.hEvent = NULL;
  257. goto done;
  258. }
  259. }
  260. // yay! save off everything.
  261. pReq->ers = ersWaiting;
  262. pReq->pret = pret;
  263. pReq->hPipe = hPipe;
  264. hev = NULL;
  265. hPipe = INVALID_HANDLE_VALUE;
  266. fRet = TRUE;
  267. done:
  268. if (hev != NULL)
  269. CloseHandle(hev);
  270. if (hPipe != INVALID_HANDLE_VALUE)
  271. {
  272. DisconnectNamedPipe(hPipe);
  273. CloseHandle(hPipe);
  274. }
  275. return fRet;
  276. }
  277. // ***************************************************************************
  278. BOOL ResetRequestObj(SRequest *pReq)
  279. {
  280. BOOL fRet = FALSE;
  281. if (pReq == NULL || pReq->ers != ersProcessing)
  282. {
  283. SetLastError(ERROR_INVALID_PARAMETER);
  284. goto done;
  285. }
  286. // clean up the thread handle.
  287. if (pReq->hth != NULL)
  288. {
  289. CloseHandle(pReq->hth);
  290. pReq->hth = NULL;
  291. }
  292. // check and make sure that our object is valid. If it ain't, nuke it
  293. // and rebuild it.
  294. if (pReq->hPipe != NULL && pReq->ol.hEvent != NULL &&
  295. pReq->pret != NULL)
  296. {
  297. // start waiting on the pipe
  298. fRet = ConnectNamedPipe(pReq->hPipe, &pReq->ol);
  299. if (fRet == FALSE)
  300. {
  301. switch(GetLastError())
  302. {
  303. case ERROR_IO_PENDING:
  304. fRet = TRUE;
  305. break;
  306. case ERROR_PIPE_CONNECTED:
  307. SetEvent(pReq->ol.hEvent);
  308. fRet = TRUE;
  309. break;
  310. default:
  311. break;
  312. }
  313. }
  314. }
  315. if (fRet == FALSE)
  316. {
  317. NukeRequestObj(pReq, FALSE);
  318. fRet = BuildRequestObj(pReq, pReq->pret);
  319. if (fRet == FALSE)
  320. goto done;
  321. }
  322. else
  323. {
  324. pReq->ers = ersWaiting;
  325. }
  326. done:
  327. return fRet;
  328. }
  329. // ***************************************************************************
  330. BOOL ProcessRequestObj(SRequest *pReq)
  331. {
  332. HANDLE hth = NULL;
  333. // should do a LoadLibrary on ersvc.dll before entering the thread.
  334. // Then, at the end of the thread, do a FreeLibraryAndExitThread() call.
  335. // This eliminates a very very small chance of a race condition (leading to an AV)
  336. // when shutting the service down.
  337. if (!pReq)
  338. {
  339. return FALSE;
  340. }
  341. pReq->hModErsvc = LoadLibraryExW(L"ersvc.dll", NULL, 0);
  342. if (pReq->hModErsvc == NULL)
  343. {
  344. return FALSE;
  345. }
  346. hth = CreateThread(NULL, 0, threadExecServer, pReq, 0, NULL);
  347. if (hth == NULL)
  348. {
  349. FreeLibrary(pReq->hModErsvc);
  350. return FALSE;
  351. }
  352. pReq->ers = ersProcessing;
  353. pReq->hth = hth;
  354. hth = NULL;
  355. return TRUE;
  356. }
  357. // ***************************************************************************
  358. BOOL ProcessRequests(SRequest *rgReqs, DWORD cReqs)
  359. {
  360. HANDLE *rghWait = NULL;
  361. DWORD iReq, cErrs = 0, dw;
  362. BOOL fRet = FALSE;
  363. if (rgReqs == NULL || cReqs == NULL || cReqs > MAXIMUM_WAIT_OBJECTS)
  364. {
  365. SetLastError(ERROR_INVALID_PARAMETER);
  366. goto done;
  367. }
  368. rghWait = (HANDLE *)MyAlloc((cReqs + 1) * sizeof(HANDLE));
  369. if (rghWait == NULL)
  370. {
  371. SetLastError(ERROR_OUTOFMEMORY);
  372. goto done;
  373. }
  374. // initially, populate all the entries in the wait array with the handles
  375. // to the overlapped events
  376. rghWait[0] = g_hevSvcStop;
  377. for(iReq = 0; iReq < cReqs; iReq++)
  378. {
  379. if (rgReqs[iReq].ol.hEvent != NULL)
  380. rghWait[iReq + 1] = rgReqs[iReq].ol.hEvent;
  381. else
  382. goto done;
  383. }
  384. for(;;)
  385. {
  386. dw = WaitForMultipleObjects(cReqs + 1, rghWait, FALSE, INFINITE);
  387. // if it's the first wait handle, then we're shutting down, so just return
  388. // TRUE
  389. if (dw == WAIT_OBJECT_0)
  390. {
  391. fRet = TRUE;
  392. goto done;
  393. }
  394. // yippy! It's one of the pipes.
  395. else if (dw >= WAIT_OBJECT_0 + 1 && dw <= WAIT_OBJECT_0 + cReqs)
  396. {
  397. SRequest *pReq;
  398. cErrs = 0;
  399. iReq = (dw - WAIT_OBJECT_0) - 1;
  400. pReq = &rgReqs[iReq];
  401. // check first to make sure we aren't shutting down. If we are, just
  402. // bail
  403. if (WaitForSingleObject(g_hevSvcStop, 0) != WAIT_TIMEOUT)
  404. {
  405. fRet = TRUE;
  406. goto done;
  407. }
  408. if (pReq->ers == ersWaiting)
  409. {
  410. fRet = ProcessRequestObj(pReq);
  411. // if we succeeded, then wait for the thread to complete instead
  412. // of the named pipe connect event
  413. if (fRet)
  414. {
  415. rghWait[iReq + 1] = pReq->hth;
  416. continue;
  417. }
  418. else
  419. {
  420. // set this so that we fall thru to the next case & get
  421. // everything cleaned up...
  422. pReq->ers = ersProcessing;
  423. }
  424. }
  425. if (pReq->ers == ersProcessing)
  426. {
  427. fRet = ResetRequestObj(pReq);
  428. if (fRet == FALSE)
  429. {
  430. if (iReq < cReqs - 1)
  431. {
  432. SRequest oReq;
  433. HANDLE hWait;
  434. CopyMemory(&oReq, pReq, sizeof(oReq));
  435. MoveMemory(&rgReqs[iReq], &rgReqs[iReq + 1],
  436. (cReqs - iReq - 1) * sizeof(SRequest));
  437. CopyMemory(&rgReqs[cReqs - 1], &oReq, sizeof(oReq));
  438. // rearrange the rghWait array as well. Otherwise it's out of sync with the object array
  439. hWait = rghWait[iReq + 1];
  440. MoveMemory(&rghWait[iReq + 1], &rghWait[iReq + 2],
  441. (cReqs - iReq - 1));
  442. rghWait[cReqs] = hWait;
  443. }
  444. cReqs--;
  445. }
  446. // ok, time to start waiting on the event to signal that a pipe
  447. // has been connected to...
  448. else
  449. {
  450. rghWait[iReq + 1] = pReq->ol.hEvent;
  451. }
  452. }
  453. }
  454. // um, this is bad.
  455. else
  456. {
  457. if (cErrs > 8)
  458. {
  459. ASSERT(FALSE);
  460. break;
  461. }
  462. cErrs++;
  463. }
  464. }
  465. done:
  466. if (rghWait != NULL)
  467. MyFree(rghWait);
  468. return fRet;
  469. }
  470. //////////////////////////////////////////////////////////////////////////////
  471. // startup & shutdown
  472. // ***************************************************************************
  473. BOOL StartERSvc(SERVICE_STATUS_HANDLE hss, SERVICE_STATUS &ss,
  474. SRequest **prgReqs, DWORD *pcReqs)
  475. {
  476. SECURITY_DESCRIPTOR sd;
  477. SECURITY_ATTRIBUTES sa;
  478. SRequest *rgReqs = NULL;
  479. HANDLE hth, hmut = NULL;
  480. DWORD dw, i, iPipe, dwType, cb, cReqs, iReqs;
  481. BOOL fRet = FALSE;
  482. HKEY hkey = NULL;
  483. ZeroMemory(&sa, sizeof(sa));
  484. if (hss == NULL || prgReqs == NULL || pcReqs == NULL)
  485. {
  486. SetLastError(ERROR_INVALID_PARAMETER);
  487. goto done;
  488. }
  489. *prgReqs = NULL;
  490. *pcReqs = NULL;
  491. if (AllocSD(&sd, ER_ACCESS_ALL, ER_ACCESS_ALL, 0) == FALSE)
  492. goto done;
  493. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  494. sa.lpSecurityDescriptor = &sd;
  495. sa.bInheritHandle = FALSE;
  496. // these two mutexes will intentionally not be free'd even if we stop the
  497. // exec server threads... These need to exist for kernel fault reporting
  498. // to work. Don't want to completely bail if we fail since we could just
  499. // have restarted the server & we don't actually need these for the
  500. // service to work.
  501. hmut = CreateMutexW(&sa, FALSE, c_wszMutKrnlName);
  502. if (hmut != NULL)
  503. {
  504. if (GetLastError() != ERROR_ALREADY_EXISTS)
  505. g_hmutKrnl = hmut;
  506. else
  507. CloseHandle(hmut);
  508. hmut = NULL;
  509. }
  510. hmut = CreateMutexW(&sa, FALSE, c_wszMutUserName);
  511. if (hmut != NULL)
  512. {
  513. if (GetLastError() != ERROR_ALREADY_EXISTS)
  514. g_hmutKrnl = hmut;
  515. else
  516. CloseHandle(hmut);
  517. hmut = NULL;
  518. }
  519. hmut = CreateMutexW(&sa, FALSE, c_wszMutShutName);
  520. if (hmut != NULL)
  521. {
  522. if (GetLastError() != ERROR_ALREADY_EXISTS)
  523. g_hmutShut = hmut;
  524. else
  525. CloseHandle(hmut);
  526. hmut = NULL;
  527. }
  528. dw = RegOpenKeyExW(HKEY_LOCAL_MACHINE, c_wszRPCfg, 0, KEY_READ, &hkey);
  529. if (dw != ERROR_SUCCESS)
  530. hkey = NULL;
  531. // find out how many pipes we're gonna create
  532. cReqs = 0;
  533. for(i = 0; i < ertiCount; i++)
  534. {
  535. if (hkey != NULL)
  536. {
  537. cb = sizeof(g_rgEvents[i].cPipes);
  538. dw = RegQueryValueExW(hkey, g_rgEvents[i].wszRVPipeCount, 0,
  539. &dwType, (LPBYTE)&g_rgEvents[i].cPipes, &cb);
  540. if (dwType != REG_DWORD || g_rgEvents[i].cPipes < c_cMinPipes)
  541. g_rgEvents[i].cPipes = c_cMinPipes;
  542. else if (g_rgEvents[i].cPipes > c_cMaxPipes)
  543. g_rgEvents[i].cPipes = c_cMaxPipes;
  544. }
  545. cReqs += g_rgEvents[i].cPipes;
  546. // ss.dwCurrentState = SERVICE_CONTINUE_PENDING;
  547. ss.dwCheckPoint++;
  548. SetServiceStatus(hss, &ss);
  549. }
  550. if (cReqs >= MAXIMUM_WAIT_OBJECTS)
  551. {
  552. SetLastError(ERROR_INVALID_PARAMETER);
  553. goto done;
  554. }
  555. // allocate the array that will hold the request info
  556. rgReqs = (SRequest *)MyAlloc(cReqs * sizeof(SRequest));
  557. if (rgReqs == NULL)
  558. {
  559. SetLastError(ERROR_OUTOFMEMORY);
  560. goto done;
  561. }
  562. // build our array of request objects
  563. fRet = TRUE;
  564. iReqs = 0;
  565. for (i = 0; i < ertiCount; i++)
  566. {
  567. dw = (g_rgEvents[i].fAllowNonLS) ? ACCESS_RW : 0;
  568. fRet = AllocSD(&g_rgsd[i], ER_ACCESS_ALL, dw, dw);
  569. if (fRet == FALSE)
  570. break;
  571. g_rgEvents[i].psd = &g_rgsd[i];
  572. // allocate request objects
  573. for (iPipe = 0; iPipe < g_rgEvents[i].cPipes; iPipe++)
  574. {
  575. rgReqs[iReqs].hPipe = INVALID_HANDLE_VALUE;
  576. InitializeCriticalSection(&rgReqs[iReqs].csReq);
  577. fRet = BuildRequestObj(&rgReqs[iReqs], &g_rgEvents[i]);
  578. if (fRet == FALSE)
  579. break;
  580. iReqs++;
  581. }
  582. if (fRet == FALSE)
  583. break;
  584. // need to update service status
  585. // ss.dwCurrentState = SERVICE_CONTINUE_PENDING;
  586. ss.dwCheckPoint++;
  587. SetServiceStatus(hss, &ss);
  588. }
  589. if (fRet == FALSE)
  590. {
  591. ss.dwCheckPoint++;
  592. ss.dwCurrentState = SERVICE_STOP_PENDING;
  593. SetServiceStatus(hss, &ss);
  594. StopERSvc(hss, ss, rgReqs, cReqs);
  595. }
  596. else
  597. {
  598. *prgReqs = rgReqs;
  599. *pcReqs = cReqs;
  600. rgReqs = NULL;
  601. cReqs = 0;
  602. }
  603. done:
  604. if (sa.lpSecurityDescriptor != NULL)
  605. FreeSD((SECURITY_DESCRIPTOR *)sa.lpSecurityDescriptor);
  606. if (rgReqs != NULL)
  607. MyFree(rgReqs);
  608. if (hkey != NULL)
  609. RegCloseKey(hkey);
  610. return fRet;
  611. }
  612. // ***************************************************************************
  613. BOOL StopERSvc(SERVICE_STATUS_HANDLE hss, SERVICE_STATUS &ss,
  614. SRequest *rgReqs, DWORD cReqs)
  615. {
  616. DWORD i;
  617. if (hss == NULL || rgReqs == NULL || cReqs == 0)
  618. {
  619. SetLastError(ERROR_INVALID_PARAMETER);
  620. return FALSE;
  621. }
  622. if (g_hevSvcStop == NULL)
  623. goto done;
  624. SetEvent(g_hevSvcStop);
  625. // update service status
  626. ss.dwCheckPoint++;
  627. // ss.dwCurrentState = SERVICE_CONTINUE_PENDING;
  628. SetServiceStatus(hss, &ss);
  629. for (i = 0; i < cReqs; i++)
  630. {
  631. NukeRequestObj(&rgReqs[i], TRUE);
  632. DeleteCriticalSection(&rgReqs[i].csReq);
  633. }
  634. for (i = 0; i < ertiCount; i++)
  635. {
  636. if (g_rgEvents[i].psd != NULL)
  637. {
  638. FreeSD(g_rgEvents[i].psd);
  639. g_rgEvents[i].psd = NULL;
  640. }
  641. }
  642. // update service status
  643. ss.dwCheckPoint++;
  644. // ss.dwCurrentState = SERVICE_CONTINUE_PENDING;
  645. SetServiceStatus(hss, &ss);
  646. done:
  647. return TRUE;
  648. }