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.

860 lines
26 KiB

  1. /*
  2. * remote checksum server
  3. *
  4. * sumserve.c main module
  5. *
  6. * program to supply lists of files and checksums from a remote server.
  7. * This program runs remotely, and is queried over a named pipe: a client
  8. * connects to us, and gives us a pathname. We then send him one at a time,
  9. * the names of all the files in the file tree starting at that path, together
  10. * with a checksum for the files.
  11. * Useful for comparing file trees that are separated by a slow link.
  12. *
  13. * outline:
  14. * this module: named pipe creation and connects - main loop
  15. *
  16. * service.c service control manager interface (start/stop)
  17. *
  18. * scan.c: service code that scans and checksums
  19. *
  20. *
  21. * Geraint Davies, july 92
  22. */
  23. #include <windows.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include "sumserve.h"
  27. #include "errlog.h"
  28. #include "server.h"
  29. #include "list.h"
  30. BOOL bNoCompression = FALSE;
  31. BOOL bTracing = FALSE;
  32. /*
  33. * error and activity log
  34. */
  35. HLOG hlogErrors;
  36. HLOG hlogEvents;
  37. /*
  38. * we keep one of these on the listConnections for each current
  39. * connection. It is created by a call to ss_logon, and should be
  40. * removed by a call to ss_logoff when the connection terminates.
  41. */
  42. typedef struct _connect {
  43. FILETIME ftLogon;
  44. char Username[256];
  45. } CONNECT, * PCONNECT;
  46. /*
  47. * list of current connections - protect by critsecConnects;
  48. */
  49. CRITICAL_SECTION critsecConnects;
  50. LIST listConnects;
  51. PCONNECT ss_logon(HANDLE hpipe);
  52. VOID ss_logoff(PCONNECT);
  53. VOID ss_sendconnects(HANDLE hpipe);
  54. /* forward declarations of procedures ----------------------------- */
  55. BOOL ss_handleclient(LPVOID arg);
  56. BOOL ss_readmessage(HANDLE hpipe, LPSTR buffer, int size);
  57. void ParseArgs(DWORD dwArgc, LPTSTR *lpszArgv);
  58. /* functions ------------------------------------------------------- */
  59. #define trace
  60. #ifdef trace
  61. static HANDLE hTraceFile = INVALID_HANDLE_VALUE;
  62. void Trace_File(LPSTR msg)
  63. {
  64. DWORD nw; /* number of bytes writtten */
  65. if (!bTracing) return;
  66. if (hTraceFile==INVALID_HANDLE_VALUE)
  67. hTraceFile = CreateFile( "sumserve.trc"
  68. , GENERIC_WRITE
  69. , FILE_SHARE_WRITE
  70. , NULL
  71. , CREATE_ALWAYS
  72. , 0
  73. , NULL
  74. );
  75. WriteFile(hTraceFile, msg, lstrlen(msg)+1, &nw, NULL);
  76. FlushFileBuffers(hTraceFile);
  77. } /* Trace_File */
  78. void Trace_Close(void)
  79. {
  80. if (hTraceFile!=INVALID_HANDLE_VALUE)
  81. CloseHandle(hTraceFile);
  82. hTraceFile = INVALID_HANDLE_VALUE;
  83. } /* Trace_Close */
  84. typedef struct {
  85. DWORD dw[5];
  86. } BLOCK;
  87. #endif //trace
  88. static void Error(PSTR Title)
  89. {
  90. Log_Write(hlogErrors, "Error %d from %s when creating main pipe", GetLastError(), Title);
  91. }
  92. HANDLE
  93. SS_CreateServerPipe(PSTR pname)
  94. {
  95. /****************************************
  96. We need security attributes for the pipe to let anyone other than the
  97. current user log on to it.
  98. ***************************************/
  99. /* Allocate DWORDs for the ACL to get them aligned. Round up to next DWORD above */
  100. DWORD Acl[(sizeof(ACL)+sizeof(ACCESS_ALLOWED_ACE)+3)/4+4]; // +4 by experiment!!
  101. SECURITY_DESCRIPTOR sd;
  102. PSECURITY_DESCRIPTOR psd = &sd;
  103. PSID psid;
  104. SID_IDENTIFIER_AUTHORITY SidWorld = SECURITY_WORLD_SID_AUTHORITY;
  105. PACL pacl = (PACL)(&(Acl[0]));
  106. SECURITY_ATTRIBUTES sa;
  107. HANDLE hpipe;
  108. if (!AllocateAndInitializeSid( &SidWorld, 1, SECURITY_WORLD_RID
  109. , 1, 2, 3, 4, 5, 6, 7
  110. , &psid
  111. )
  112. ) {
  113. Error("AllocateAndInitializeSid");
  114. return(INVALID_HANDLE_VALUE);
  115. }
  116. if (!InitializeAcl(pacl, sizeof(Acl), ACL_REVISION)){
  117. Error("InitializeAcl");
  118. return(INVALID_HANDLE_VALUE);
  119. }
  120. if (!AddAccessAllowedAce(pacl, ACL_REVISION, GENERIC_WRITE|GENERIC_READ, psid)){
  121. Error("AddAccessAllowedAce");
  122. return(INVALID_HANDLE_VALUE);
  123. }
  124. if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION)){
  125. Error("InitializeSecurityDescriptor");
  126. return(INVALID_HANDLE_VALUE);
  127. }
  128. if (!SetSecurityDescriptorDacl(psd, TRUE, pacl, FALSE)){
  129. Error("SetSecurityDescriptorDacl");
  130. return(INVALID_HANDLE_VALUE);
  131. }
  132. sa.nLength = sizeof(sa);
  133. sa.lpSecurityDescriptor = psd;
  134. sa.bInheritHandle = TRUE;
  135. /* We now have a good security descriptor! */
  136. dprintf1(("creating new pipe instance\n"));
  137. hpipe = CreateNamedPipe(pname, /* pipe name */
  138. PIPE_ACCESS_DUPLEX, /* both read and write */
  139. PIPE_WAIT|PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE,
  140. PIPE_UNLIMITED_INSTANCES,
  141. 0, 0, /* dynamic buffer allocation*/
  142. 5000, /* def. timeout 5 seconds */
  143. &sa /* security descriptor */
  144. );
  145. FreeSid(psid);
  146. if (hpipe == INVALID_HANDLE_VALUE) {
  147. Error("CreateNamedPipe");
  148. return(INVALID_HANDLE_VALUE);
  149. }
  150. return(hpipe);
  151. }
  152. /* program main loop
  153. *
  154. * creates the named pipe, and loops waiting for client connections and
  155. * calling ss_handleclient for each connection. only exits when told
  156. * to by a client.
  157. *
  158. * currently permits only one client connection at once.
  159. */
  160. VOID
  161. MainLoop(DWORD dwArgc, LPTSTR *lpszArgv)
  162. {
  163. char msg[400];
  164. HANDLE hpipe;
  165. DWORD threadid;
  166. ParseArgs(dwArgc, lpszArgv);
  167. /*
  168. * initialise error and activity logs
  169. */
  170. hlogErrors = Log_Create();
  171. hlogEvents = Log_Create();
  172. Log_Write(hlogEvents, "Checksum service started");
  173. /* initialise connection list and protective critsec */
  174. InitializeCriticalSection(&critsecConnects);
  175. List_Init();
  176. listConnects = List_Create();
  177. if (bTracing){
  178. SYSTEMTIME st;
  179. char msg[120];
  180. GetSystemTime(&st);
  181. wsprintf(msg, "Sumserve trace, started %hd:%hd on %hd/%hd/%hd (British notation)\n"
  182. , st.wHour, st.wMinute, st.wDay, st.wMonth, st.wYear);
  183. }
  184. /* create the named pipe at the known name NPNAME on this server */
  185. /* build the correct syntax for a named pipe on the local machine,
  186. * with the pipe name being NPNAME - thus the full name should be
  187. * \\.\pipe\NPNAME
  188. */
  189. sprintf(msg, "\\\\.\\pipe\\%s", NPNAME);
  190. /*
  191. * loop creating instances of the named pipe and connecting to
  192. * clients.
  193. *
  194. * When a client connects, we spawn a thread to handle him, and
  195. * we create another instance of the named pipe to service
  196. * further clients.
  197. *
  198. * if we receive a quit message (TRUE return from handleclient)
  199. * we exit here so that no new clients will be connected.
  200. * the process will exit when all the client requests are
  201. * finished.
  202. */
  203. for (;;) {
  204. hpipe = SS_CreateServerPipe(msg);
  205. if (hpipe == INVALID_HANDLE_VALUE) {
  206. return;
  207. }
  208. dprintf1(("Waiting for client to connect to main pipe %x\n", hpipe));
  209. if (ConnectNamedPipe(hpipe, NULL)) {
  210. /* we have a client connection */
  211. dprintf1(("Client has connected\n"));
  212. /*
  213. * create a thread to service all requests
  214. */
  215. CreateThread(NULL, 0,
  216. (LPTHREAD_START_ROUTINE) ss_handleclient,
  217. (LPVOID) hpipe, 0, &threadid);
  218. dprintf1(("created thread %ld for pipe %x\n", threadid, hpipe));
  219. }
  220. }
  221. #ifdef trace
  222. Trace_Close();
  223. #endif
  224. /* free up logs */
  225. Log_Delete(hlogErrors);
  226. Log_Delete(hlogEvents);
  227. List_Destroy(&listConnects);
  228. DeleteCriticalSection(&critsecConnects);
  229. return;
  230. }
  231. /* collect arguments: -n means bNoCompression = TRUE, -t means bTracing = TRUE */
  232. void
  233. ParseArgs(DWORD dwArgc, LPTSTR *lpszArgv)
  234. {
  235. DWORD i;
  236. PSTR ps;
  237. for (i = 1; i < dwArgc; i++) {
  238. ps = lpszArgv[i];
  239. /* is this an option ? */
  240. if ((ps[0] == '-') || (ps[0] == '/')) {
  241. switch(ps[1]) {
  242. case 'n':
  243. case 'N':
  244. bNoCompression = TRUE;
  245. break;
  246. #ifdef trace
  247. case 't':
  248. case 'T':
  249. bTracing = TRUE;
  250. break;
  251. #endif //trace
  252. default:
  253. Log_Write(hlogErrors, "Bad option(s) ignored");
  254. return;
  255. }
  256. }
  257. else {
  258. Log_Write(hlogErrors, "Bad argument(s) ignored");
  259. return;
  260. }
  261. }
  262. } /* ParseArgs */
  263. /*
  264. * handle a client connection. This routine is called in a separate thread
  265. * to service a given client.
  266. *
  267. * loop reading messages until the client sends a session exit or
  268. * program exit code, or until the pipe connection goes away.
  269. *
  270. * return TRUE if the server is to exit (indicated by a program exit
  271. * command SSREQ_EXIT from the client)
  272. */
  273. BOOL
  274. ss_handleclient(LPVOID arg)
  275. {
  276. HANDLE hpipe = (HANDLE) arg;
  277. SSREQUEST req;
  278. SSNEWREQ newreq;
  279. LPSTR p1, p2;
  280. PFNAMELIST connects = NULL;
  281. BOOL bExitServer = FALSE;
  282. LONG lVersion = 0;
  283. BOOL bDirty = TRUE; /* cleared on clean exit */
  284. PCONNECT pLogon;
  285. try {
  286. /* make a logon entry in the connections table*/
  287. pLogon = ss_logon(hpipe);
  288. // dprintf1(("Client handler for pipe %x\n", hpipe));
  289. /* loop indefinitely - exit only from within the loop if
  290. * the connection goes away or we receive an exit command
  291. */
  292. for (; ; ) {
  293. /* read a message from the pipe - if false,
  294. * connection is dropped.
  295. */
  296. if (!ss_readmessage(hpipe, (LPSTR) &newreq, sizeof(newreq))) {
  297. break;
  298. }
  299. if (newreq.lCode<0) {
  300. lVersion = newreq.lVersion;
  301. dprintf1(("Client for pipe %x is at Version %d\n", hpipe, lVersion));
  302. newreq.lCode = -newreq.lCode;
  303. }
  304. else { /* juggle the fields to get them right */
  305. memcpy(&req, &newreq, sizeof(req));
  306. /* lCode is already in the right place */
  307. dprintf1(("Version 0 (i.e. down level client) for pipe %x\n", hpipe));
  308. newreq.lVersion = 0;
  309. memcpy(&newreq.szPath, &req.szPath, MAX_PATH*sizeof(char));
  310. }
  311. if (newreq.lVersion>SS_VERSION) /* WE are down level! */
  312. {
  313. ss_sendnewresp( hpipe, SS_VERSION, SSRESP_BADVERS
  314. , 0,0, 0,0, NULL);
  315. /* Sorry - can't help - clean exit */
  316. Log_Write(hlogErrors,
  317. "server is down level! Please upgrade! Client wants %d"
  318. , newreq.lVersion);
  319. FlushFileBuffers(hpipe);
  320. break;
  321. }
  322. if (newreq.lCode == SSREQ_EXIT) {
  323. /* exit the program */
  324. Log_Write(hlogErrors, "Server exit request from %s - Ignored",
  325. pLogon->Username);
  326. /* clean exit */
  327. FlushFileBuffers(hpipe);
  328. /*
  329. * now exit the server -
  330. * returning bExitServer from this function will
  331. * cause MainLoop to exit. This will result in
  332. * the service being stopped, and the process exiting.
  333. */
  334. bExitServer = TRUE;
  335. #ifdef trace
  336. Trace_Close();
  337. #endif
  338. break;
  339. } else if (newreq.lCode == SSREQ_END) {
  340. /* clean exit */
  341. dprintf1(("Server end session request for pipe %x\n", hpipe));
  342. FlushFileBuffers(hpipe);
  343. break;
  344. } else if (newreq.lCode == SSREQ_SCAN
  345. || newreq.lCode == SSREQ_QUICKSCAN) {
  346. /* please scan the following file or dir,
  347. * and return the list of files and
  348. * checksums.
  349. */
  350. Log_Write(hlogEvents, "%s scan for %s",
  351. pLogon->Username, newreq.szPath);
  352. #ifdef SECURE
  353. /* lower security to the client's level */
  354. if (!ImpersonateNamedPipeClient(hpipe)) {
  355. dprintf1(("Client impersonate failed %d\n",
  356. GetLastError() ));
  357. }
  358. #endif
  359. if (!ss_scan( hpipe, newreq.szPath, lVersion
  360. , (newreq.lCode == SSREQ_SCAN)
  361. , 0!=(newreq.lFlags&INCLUDESUBS)
  362. )
  363. ) {
  364. /* return to our own security token */
  365. RevertToSelf();
  366. dprintf1(("connection lost during scan for pipe %x\n", hpipe));
  367. break;
  368. }
  369. /* return to our own security token */
  370. RevertToSelf();
  371. } else if (newreq.lCode == SSREQ_UNC) {
  372. dprintf1(("connect request for pipe %x\n", hpipe));
  373. /* this packet has two strings in the buffer, first
  374. * is the password, second is the server
  375. */
  376. p1 = newreq.szPath;
  377. p2 = &p1[strlen(p1) + 1];
  378. /* remember to add the connect name to our list
  379. * of servers to disconnect from at end of client
  380. * session
  381. */
  382. connects = ss_handleUNC (hpipe, lVersion, p1, p2
  383. , connects);
  384. } else if (newreq.lCode == SSREQ_FILE) {
  385. Log_Write(hlogEvents, "%s copy file %s",
  386. pLogon->Username, newreq.szPath);
  387. ss_sendfile(hpipe, newreq.szPath, lVersion);
  388. } else if (newreq.lCode == SSREQ_FILES) {
  389. Log_Write(hlogEvents, "%s bulk copy request",
  390. pLogon->Username);
  391. if (!ss_sendfiles(hpipe, lVersion)) {
  392. RevertToSelf();
  393. dprintf1(("Sendfiles completed with error on pipe %x\n", hpipe));
  394. break;
  395. }
  396. } else if (newreq.lCode == SSREQ_NEXTFILE) {
  397. Log_Write(hlogErrors,
  398. "file list from %s (pipe %x) request out of sequence! (ignored)",
  399. pLogon->Username, hpipe);
  400. } else if (newreq.lCode == SSREQ_ERRORLOG) {
  401. Log_Send(hpipe, hlogErrors);
  402. } else if (newreq.lCode == SSREQ_EVENTLOG) {
  403. Log_Send(hpipe, hlogEvents);
  404. } else if (newreq.lCode == SSREQ_CONNECTS) {
  405. ss_sendconnects(hpipe);
  406. } else {
  407. /* packet error ? - carry on anyway */
  408. Log_Write(hlogErrors,
  409. "error in message from %s code: %d",
  410. pLogon->Username, newreq.lCode);
  411. }
  412. }
  413. /* we break out of the loop at end of client session */
  414. /* close this pipe instance */
  415. DisconnectNamedPipe(hpipe);
  416. CloseHandle(hpipe);
  417. /* clean all connections made for this client */
  418. ss_cleanconnections(connects);
  419. /* exit this server thread */
  420. dprintf1(("thread %ld exiting on behalf of pipe %x\n", GetCurrentThreadId(), hpipe));
  421. bDirty = FALSE;
  422. }
  423. except (EXCEPTION_EXECUTE_HANDLER) {
  424. if (bDirty) {
  425. Log_Write(hlogErrors,
  426. "!!Exception on thread %ld. Exiting on behalf of %s"
  427. , GetCurrentThreadId(), pLogon->Username);
  428. try {
  429. DisconnectNamedPipe(hpipe);
  430. CloseHandle(hpipe);
  431. }
  432. except (EXCEPTION_EXECUTE_HANDLER) {
  433. /* Oh dear - let's just go home! */
  434. }
  435. }
  436. else
  437. dprintf1(( "Thread %ld exiting on behalf of pipe %x\n"
  438. , GetCurrentThreadId(), hpipe));
  439. }
  440. /* note that we have logged off */
  441. ss_logoff(pLogon);
  442. return(bExitServer);
  443. } /* ss_handle_client */
  444. /* build and send a response packet to the client. Check for network
  445. * errors, and retry (unless the pipe is broken) up to 10 times.
  446. *
  447. * if write succeeds - return TRUE.
  448. * if failure - return FALSE to indicate connection is dropped.
  449. */
  450. BOOL
  451. ss_sendnewresp( HANDLE hpipe
  452. , long lVersion
  453. , long lCode
  454. , ULONG ulSize /* used for Win32 error code for SSRESP_ERRROR */
  455. , ULONG ulSum
  456. , DWORD dwLowTime
  457. , DWORD dwHighTime
  458. , PSTR szFile
  459. )
  460. {
  461. SSNEWRESP resp;
  462. if (lVersion==0) {
  463. return ss_sendresponse(hpipe, lCode, ulSize, ulSum, szFile);
  464. }
  465. resp.lVersion = lVersion;
  466. resp.lResponse = LRESPONSE;
  467. resp.lCode = lCode;
  468. resp.ulSize = ulSize;
  469. resp.ulSum = ulSum;
  470. resp.ft_lastwrite.dwLowDateTime = dwLowTime;
  471. resp.ft_lastwrite.dwHighDateTime = dwHighTime;
  472. if (szFile != NULL) {
  473. lstrcpy(resp.szFile, szFile);
  474. }
  475. return(ss_sendblock(hpipe, (PSTR) &resp, sizeof(resp)));
  476. } /* ss_sendnewresp */
  477. /* build and send a response packet to the client. Check for network
  478. * errors, and retry (unless the pipe is broken) up to 10 times.
  479. *
  480. * if write succeeds - return TRUE.
  481. * if failure - return FALSE to indicate connection is dropped.
  482. */
  483. BOOL
  484. ss_sendresponse(HANDLE hpipe, long lCode, ULONG ulSize, ULONG ulSum, PSTR szFile)
  485. {
  486. SSRESPONSE resp;
  487. resp.lCode = lCode;
  488. resp.ulSize = ulSize;
  489. resp.ulSum = ulSum;
  490. if (szFile != NULL) {
  491. lstrcpy(resp.szFile, szFile);
  492. }
  493. return(ss_sendblock(hpipe, (PSTR) &resp, sizeof(resp)));
  494. }
  495. /*
  496. * send a block of data or response packet to the named pipe.
  497. *
  498. * return TRUE if ok, or false if connection dropped
  499. */
  500. BOOL
  501. ss_sendblock(HANDLE hpipe, PSTR buffer, int length)
  502. {
  503. int size, count, errorcode;
  504. /* loop retrying the send until it goes ok */
  505. for (count = 0; count < 10; count++) {
  506. #ifdef trace
  507. { char msg[80];
  508. BLOCK * pb;
  509. pb = (BLOCK *) buffer;
  510. wsprintf( msg, "sendblock on %x: %x %x %x %x %x\n"
  511. , hpipe, pb->dw[0], pb->dw[1], pb->dw[2], pb->dw[3], pb->dw[4]);
  512. Trace_File(msg);
  513. }
  514. #endif
  515. if (WriteFile(hpipe, buffer, length, (LPDWORD)(&size), NULL)) {
  516. /* no error reported - was everything written?*/
  517. if (size != length) {
  518. #ifdef trace
  519. { char msg[80];
  520. wsprintf(msg, " !!Bad length send for %x \n", hpipe);
  521. Trace_File(msg);
  522. }
  523. #endif
  524. /* write was NOT ok - report and retry */
  525. printf("pipe write size differs for pipe %x\n", hpipe);
  526. continue; // ??? will this confuse client
  527. } else {
  528. #ifdef trace
  529. { char msg[80];
  530. wsprintf(msg, " good send for %x \n", hpipe);
  531. Trace_File(msg);
  532. }
  533. #endif
  534. /* all ok */
  535. return(TRUE);
  536. }
  537. }
  538. #ifdef trace
  539. { char msg[80];
  540. wsprintf(msg, " !!Bad send for %x \n", hpipe);
  541. Trace_File(msg);
  542. }
  543. #endif
  544. /* an error occurred */
  545. switch( (errorcode = (int)GetLastError())) {
  546. case ERROR_NO_DATA:
  547. case ERROR_BROKEN_PIPE:
  548. /* pipe connection lost - forget it */
  549. dprintf1(("pipe %x broken on write\n", hpipe));
  550. return(FALSE);
  551. default:
  552. Log_Write(hlogErrors, "write error %d on pipe %x",
  553. errorcode, hpipe);
  554. break;
  555. }
  556. }
  557. /* retry count reached - abandon this attempt */
  558. Log_Write(hlogErrors,
  559. "retry count reached on pipe %s - write error", hpipe);
  560. return(FALSE);
  561. }
  562. /* read a message from a pipe, allowing for network errors
  563. *
  564. * if error occurs, retry up to 10 times unless error code
  565. * indicates that pipe is broken - in which case, give up.
  566. *
  567. * return TRUE if all ok, or FALSE to mean the connection is broken,
  568. * abort this client.
  569. */
  570. BOOL
  571. ss_readmessage(HANDLE hpipe, LPSTR buffer, int size)
  572. {
  573. int count;
  574. int actualsize;
  575. int errorcode;
  576. /* retry up to 10 times */
  577. for (count = 0; count < 10; count++ ) {
  578. // dprintf1(("waiting for read of pipe %x ...\n", hpipe));
  579. #ifdef trace
  580. { char msg[80];
  581. wsprintf(msg, "ReadFile for pipe %x ...", hpipe );
  582. Trace_File(msg);
  583. }
  584. #endif
  585. if (ReadFile(hpipe, buffer, size, (LPDWORD)(&actualsize), NULL)) {
  586. #ifdef trace
  587. { char msg[80];
  588. BLOCK * pb;
  589. pb = (BLOCK *) buffer;
  590. wsprintf(msg, " Good ReadFile for %x: %x %x %x %x %x\n"
  591. , hpipe, pb->dw[0], pb->dw[1], pb->dw[2], pb->dw[3], pb->dw[4]);
  592. Trace_File(msg);
  593. }
  594. #endif
  595. /* everything ok */
  596. // dprintf1((" pipe %x read OK\n", hpipe));
  597. return(TRUE);
  598. }
  599. #ifdef trace
  600. { char msg[80];
  601. wsprintf(msg, "!!Bad ReadFile for %x\n", hpipe );
  602. Trace_File(msg);
  603. }
  604. #endif
  605. /* error occurred - check code */
  606. switch((errorcode = (int)GetLastError())) {
  607. case ERROR_BROKEN_PIPE:
  608. /* connection broken. no point in retrying */
  609. dprintf1(("pipe %x broken on read\n", hpipe));
  610. return(FALSE);
  611. case ERROR_MORE_DATA:
  612. /* the message sent is larger than our buffer.
  613. * this is an internal error - report it and carryon
  614. */
  615. Log_Write(hlogErrors,
  616. "error from pipe %x - message too large", hpipe);
  617. return(TRUE);
  618. default:
  619. Log_Write(hlogErrors,
  620. "pipe %x read error %d", hpipe, errorcode);
  621. break;
  622. }
  623. }
  624. Log_Write(hlogErrors, "retry count reached on pipe %x read error", hpipe);
  625. return(FALSE);
  626. }
  627. /*
  628. * note a logon, and return a logon entry that should be removed at
  629. * logoff time
  630. */
  631. PCONNECT ss_logon(HANDLE hpipe)
  632. {
  633. PCONNECT pLogon;
  634. SYSTEMTIME systime;
  635. char msg[256];
  636. EnterCriticalSection(&critsecConnects);
  637. pLogon = List_NewLast(listConnects, sizeof(CONNECT));
  638. LeaveCriticalSection(&critsecConnects);
  639. GetSystemTime(&systime);
  640. SystemTimeToFileTime(&systime, &pLogon->ftLogon);
  641. GetNamedPipeHandleState(
  642. hpipe,
  643. NULL,
  644. NULL,
  645. NULL,
  646. NULL,
  647. pLogon->Username,
  648. sizeof(pLogon->Username));
  649. /* log the connect event in the main log*/
  650. wsprintf(msg, "%s connected", pLogon->Username);
  651. Log_WriteData(hlogEvents, &pLogon->ftLogon, msg);
  652. return(pLogon);
  653. }
  654. /*
  655. * remove a current connection from the connections list
  656. */
  657. VOID ss_logoff(PCONNECT pLogon)
  658. {
  659. /* note the logoff event in the main log */
  660. Log_Write(hlogEvents, "%s connection terminated", pLogon->Username);
  661. /* remove the entry from the list */
  662. EnterCriticalSection(&critsecConnects);
  663. List_Delete(pLogon);
  664. LeaveCriticalSection(&critsecConnects);
  665. }
  666. /*
  667. * send the current-connections log
  668. *
  669. * Current connections are held on a list - we need to build a standard
  670. * log from the current list and then send that.
  671. */
  672. VOID ss_sendconnects(HANDLE hpipe)
  673. {
  674. HLOG hlog;
  675. PCONNECT pconn;
  676. hlog = Log_Create();
  677. EnterCriticalSection(&critsecConnects);
  678. List_TRAVERSE(listConnects, pconn) {
  679. Log_WriteData(hlog, &pconn->ftLogon, pconn->Username);
  680. }
  681. LeaveCriticalSection(&critsecConnects);
  682. Log_Send(hpipe, hlog);
  683. Log_Delete(hlog);
  684. }