[x]
Posted via EE Mobile

Search, ask, and monitor your questions on the go with EE Mobile. Visit Experts Exchange from your mobile device and never be out of touch again.

Question
[x]
Attachment Details

Compiling C++ Code - Works in Min-GW - Want it compiled using Visual Studio

Asked by SysMicro in Microsoft Visual C++.Net, Microsoft Visual C++, Microsoft Visual Interdev

Tags: C++ compile

Does anyone know Visual Studio or C++ code? Im trying to compile this source code for check_mk_agent.exe however its generating 77 errors and 18 warnings!

Attached compile log and code below for reference...

Hope someone can help!

Im doing a recompile with Visual Studio to see if the app crashing stops as the Min-GW (Linux) compiler is normally used!

Is the code incorrect?
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359:
360:
361:
362:
363:
364:
365:
366:
367:
368:
369:
370:
371:
372:
373:
374:
375:
376:
377:
378:
379:
380:
381:
382:
383:
384:
385:
386:
387:
388:
389:
390:
391:
392:
393:
394:
395:
396:
397:
398:
399:
400:
401:
402:
403:
404:
405:
406:
407:
408:
409:
410:
411:
412:
413:
414:
415:
416:
417:
418:
419:
420:
421:
422:
423:
424:
425:
426:
427:
428:
429:
430:
431:
432:
433:
434:
435:
436:
437:
438:
439:
440:
441:
442:
443:
444:
445:
446:
447:
448:
449:
450:
451:
452:
453:
454:
455:
456:
457:
458:
459:
460:
461:
462:
463:
464:
465:
466:
467:
468:
469:
470:
471:
472:
473:
474:
475:
476:
477:
478:
479:
480:
481:
482:
483:
484:
485:
486:
487:
488:
489:
490:
491:
492:
493:
494:
495:
496:
497:
498:
499:
500:
501:
502:
503:
504:
505:
506:
507:
508:
509:
510:
511:
512:
513:
514:
515:
516:
517:
518:
519:
520:
521:
522:
523:
524:
525:
526:
527:
528:
529:
530:
531:
532:
533:
534:
535:
536:
537:
538:
539:
540:
541:
542:
543:
544:
545:
546:
547:
548:
549:
550:
551:
552:
553:
554:
555:
556:
557:
558:
559:
560:
561:
562:
563:
564:
565:
566:
567:
568:
569:
570:
571:
572:
573:
574:
575:
576:
577:
578:
579:
580:
581:
582:
583:
584:
585:
586:
587:
588:
589:
590:
591:
592:
593:
594:
595:
596:
597:
598:
599:
600:
601:
602:
603:
604:
605:
606:
607:
608:
609:
610:
611:
612:
613:
614:
615:
616:
617:
618:
619:
620:
621:
622:
623:
624:
625:
626:
627:
628:
629:
630:
631:
632:
633:
634:
635:
636:
637:
638:
639:
640:
641:
642:
643:
644:
645:
646:
647:
648:
649:
650:
651:
652:
653:
654:
655:
656:
657:
658:
659:
660:
661:
662:
663:
664:
665:
666:
667:
668:
669:
670:
671:
672:
673:
674:
675:
676:
677:
678:
679:
680:
681:
682:
683:
684:
685:
686:
687:
688:
689:
690:
691:
692:
693:
694:
695:
696:
697:
698:
699:
700:
701:
702:
703:
704:
705:
706:
707:
708:
709:
710:
711:
712:
713:
714:
715:
716:
717:
718:
719:
720:
721:
722:
723:
724:
725:
726:
727:
728:
729:
730:
731:
732:
733:
734:
735:
736:
737:
738:
739:
740:
741:
742:
743:
744:
745:
746:
747:
748:
749:
750:
751:
752:
753:
754:
755:
756:
757:
758:
759:
760:
761:
762:
763:
764:
765:
766:
767:
768:
769:
770:
771:
772:
773:
774:
775:
776:
777:
778:
779:
780:
781:
782:
783:
784:
785:
786:
787:
788:
789:
790:
791:
792:
793:
794:
795:
796:
797:
798:
799:
800:
801:
802:
803:
804:
805:
806:
807:
808:
809:
810:
811:
812:
813:
814:
815:
816:
817:
818:
819:
820:
821:
822:
823:
824:
825:
826:
827:
828:
829:
830:
831:
832:
833:
834:
835:
836:
837:
838:
839:
840:
841:
842:
843:
844:
845:
846:
847:
848:
849:
850:
851:
852:
853:
854:
855:
856:
857:
858:
859:
860:
861:
862:
863:
864:
865:
866:
867:
868:
869:
870:
871:
872:
873:
874:
875:
876:
877:
878:
879:
880:
881:
882:
883:
884:
885:
886:
887:
888:
889:
890:
891:
892:
893:
894:
895:
896:
897:
898:
899:
900:
901:
902:
903:
904:
905:
906:
907:
908:
909:
910:
911:
912:
913:
914:
915:
916:
917:
918:
919:
920:
921:
922:
923:
924:
925:
926:
927:
928:
929:
930:
931:
932:
933:
934:
935:
936:
937:
938:
939:
940:
941:
942:
943:
944:
945:
946:
947:
948:
949:
950:
951:
952:
953:
954:
955:
956:
957:
958:
959:
960:
961:
962:
963:
964:
965:
966:
967:
968:
969:
970:
971:
972:
973:
974:
975:
976:
977:
978:
979:
980:
981:
982:
983:
984:
985:
986:
987:
988:
989:
990:
991:
992:
993:
994:
995:
996:
997:
998:
999:
1000:
1001:
1002:
1003:
1004:
1005:
1006:
1007:
1008:
1009:
1010:
1011:
1012:
1013:
1014:
1015:
1016:
1017:
1018:
1019:
1020:
1021:
1022:
1023:
1024:
1025:
1026:
1027:
1028:
1029:
1030:
1031:
1032:
1033:
1034:
1035:
1036:
1037:
1038:
1039:
1040:
1041:
1042:
1043:
1044:
1045:
1046:
1047:
1048:
1049:
1050:
1051:
1052:
1053:
1054:
1055:
1056:
1057:
1058:
1059:
1060:
1061:
1062:
1063:
1064:
1065:
1066:
1067:
1068:
1069:
1070:
1071:
1072:
1073:
1074:
1075:
1076:
1077:
1078:
1079:
1080:
1081:
1082:
1083:
1084:
1085:
1086:
1087:
1088:
1089:
1090:
1091:
1092:
1093:
1094:
1095:
1096:
1097:
1098:
1099:
1100:
1101:
1102:
1103:
1104:
1105:
1106:
1107:
1108:
1109:
1110:
1111:
1112:
1113:
1114:
1115:
1116:
1117:
1118:
1119:
1120:
1121:
1122:
1123:
1124:
1125:
1126:
1127:
1128:
1129:
1130:
1131:
1132:
1133:
1134:
1135:
1136:
1137:
1138:
1139:
1140:
1141:
1142:
1143:
1144:
1145:
1146:
1147:
1148:
1149:
1150:
1151:
1152:
1153:
1154:
1155:
1156:
1157:
1158:
1159:
1160:
1161:
1162:
1163:
1164:
1165:
1166:
1167:
1168:
1169:
1170:
1171:
1172:
1173:
1174:
1175:
1176:
1177:
1178:
1179:
1180:
1181:
1182:
1183:
1184:
1185:
1186:
1187:
1188:
1189:
1190:
1191:
1192:
1193:
1194:
1195:
1196:
1197:
1198:
1199:
1200:
1201:
1202:
1203:
1204:
1205:
1206:
1207:
1208:
1209:
1210:
1211:
1212:
1213:
1214:
1215:
1216:
1217:
1218:
1219:
1220:
1221:
1222:
1223:
1224:
1225:
1226:
1227:
1228:
1229:
1230:
1231:
1232:
1233:
1234:
1235:
1236:
1237:
1238:
1239:
1240:
1241:
1242:
1243:
1244:
1245:
1246:
1247:
1248:
1249:
1250:
1251:
1252:
1253:
1254:
1255:
1256:
1257:
1258:
1259:
1260:
1261:
1262:
// +------------------------------------------------------------------+
// |          _           _           _       _   __   ____ ___       |
// |       __| |_  ___ __| |__  _ __ | |__   / | /  \ |__ /( _ )      |
// |      / _| ' \/ -_) _| / / | '  \| / /   | || () | |_ \/ _ \      |
// |      \__|_||_\___\__|_\_\_|_|_|_|_\_\   |_(_)__(_)___/\___/      |
// |                                            check_mk 1.0.38       |
// |                                                                  |
// | Copyright Mathias Kettner 2009                mk@mathias-kettner |
// +------------------------------------------------------------------+
// 
// This file is part of check_mk 1.0.38.
// The official homepage is at http://mathias-kettner.de/check_mk.
// 
// check_mk is free software;  you can redistribute it and/or modify it
// under the  terms of the  GNU General Public License  as published by
// the Free Software Foundation in version 2.  check_mk is  distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
// out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
// PARTICULAR PURPOSE. See the  GNU General Public License for more de-
// ails.  You should have  received  a copy of the  GNU  General Public
// License along with GNU Make; see the file  COPYING.  If  not,  write
// to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
// Boston, MA 02110-1301 USA.
 
 
// Looking for documentation on Win32-API? Here are some of the
// documents that I used:
 
// Registry:
// http://msdn.microsoft.com/en-us/library/ms724897.aspx
 
// Performance-Counters:
// http://msdn.microsoft.com/en-us/library/aa373178(VS.85).aspx
 
// Eventlogs:
// http://msdn.microsoft.com/en-us/library/aa363672(VS.85).aspx
// http://msdn.microsoft.com/en-us/library/bb427356(VS.85).aspx
 
// System Error Codes:
// http://msdn.microsoft.com/en-us/library/ms681381(VS.85).aspx
 
// This program needs at least windows version 0x0500
// (Window 2000 / Windows XP)
#define WINVER 0x0500
 
#include <stdio.h>
#include <windows.h>
#include <winbase.h>
#include <winreg.h>    // performance counters from registry
#include <tlhelp32.h>  // list of processes
#include <winsock2.h>
#include <stdarg.h>
#include <time.h>
 
#define CHECK_MK_VERSION "1.0.38"
#define CHECK_MK_AGENT_PORT 6556
#define SERVICE_NAME "Check_MK_Agent"
#define KiloByte 1024
 
bool do_tcp = false;
bool should_terminate = false;
bool logwatch_send_initial_entries = false;
bool logwatch_suppress_info = true;
 
// dynamic buffer for event log entries. Grows with the
// time as needed. Never shrinked.
char *eventlog_buffer = 0;
int eventlog_buffer_size = 0;
 
// Our memory of what event logs we know and up to
// which record entry we have seen its messages so
// far. We do not want to make use of C++ features
// here so sorry for the mess...
unsigned num_eventlogs = 0;
#define  MAX_EVENTLOGS 128
DWORD    known_record_numbers[MAX_EVENTLOGS];
char    *eventlog_names[MAX_EVENTLOGS];
bool     newly_found[MAX_EVENTLOGS];
 
 
#ifdef DEBUG
void debug(char *text)
{
    FILE *debugout = fopen("C:\\check_mk_agent.log", "a");
    if (debugout) {
      fprintf(debugout, "%s\n", text);
      fflush(debugout);
      fclose(debugout);
    }
}
#else
#define debug(C) 
#endif
 
bool verbose_mode = false;
void verbose(const char *format, ...)
{
    if (!verbose_mode)
      return;
 
    va_list ap;
    va_start(ap, format);
    printf("DEBUG: ");
    vprintf(format, ap);
    printf("\n");
    fflush(stdout);
}
   
 
 
void outputCounter(SOCKET &out, BYTE *datablock, int counter, 
               PERF_OBJECT_TYPE *objectPtr, PERF_COUNTER_DEFINITION *counterPtr);
void outputCounterValue(SOCKET &out, PERF_COUNTER_BLOCK *counterBlockPtr, int size, unsigned offset);
double current_time();
 
 
// determine system root by reading the environment variable
// %SystemRoot%. This variable is used in the registry entries
// that describe eventlog messages.
const char *system_root()
{
    static char root[128];
    if (0 < GetWindowsDirectory(root, sizeof(root)))
      return root;
    else
      return "C:\\WINDOWS";
}
 
 
char *llu_to_string(unsigned long long value)
{
    static char buffer[64];
 
    if (value == 0) {
      strcpy(buffer, "0");
        return buffer;
    }
 
    buffer[63] = 0;
    
    char *write = buffer + 63;
    while (value > 0) {
      if (write <= buffer) {
          strcpy(buffer, "(invalid)");
          return buffer;
      }
      char digit = (value % 10) + '0';
      *--write = digit;
      value = value / 10;
    }
    return write;
}
 
 
 
void output(SOCKET &out, const char *format, ...)
{
    static char outbuffer[4096];
 
    va_list ap;
    va_start(ap, format);
    int len = vsnprintf(outbuffer, sizeof(outbuffer), format, ap);
    if (do_tcp) {
      while (!should_terminate) {
          int result = send(out, outbuffer, len, 0);
          if (result == SOCKET_ERROR) {
            debug("send() failed");
            int error = WSAGetLastError();
            if (error == WSAEINTR) {
                debug("INTR. Nochmal...");
                continue;
            }
            else if (error == WSAEINPROGRESS) {
                debug("INPROGRESS. Nochmal...");
                continue;
            }
            else if (error == WSAEWOULDBLOCK) {
                debug("WOULDBLOCK. Komisch. Breche ab...");
                break;
            }
            else {
                debug("Anderer Fehler. Gebe auf\n");
                break;
            }
          }
          else if (result == 0)
            debug("send() returned 0");
          else if (result != len)
            debug("send() sent too few bytes");
          break;
      }
    }    
    else
      fwrite(outbuffer, len, 1, stdout);
}
 
 
void section_df(SOCKET &out)
{
    output(out, "<<<df>>>\n");
    TCHAR buffer[4096];
    DWORD len = GetLogicalDriveStrings(sizeof(buffer), buffer);
 
    TCHAR *end = buffer + len;
    TCHAR *drive = buffer;
    while (drive < end) {
      UINT drvType = GetDriveType(drive);
      if (drvType == DRIVE_FIXED)  // only process local harddisks
      {
          ULARGE_INTEGER free_avail, total, free;
          free_avail.QuadPart = 0;
          total.QuadPart = 0;
          free.QuadPart = 0;
          int returnvalue = GetDiskFreeSpaceEx(drive, &free_avail, &total, &free);
          if (returnvalue > 0) {
            double perc_used = 0;
            if (total.QuadPart > 0)
                perc_used = 100 - (100 * free_avail.QuadPart / total.QuadPart);
            
            TCHAR fsname[128];
            if (!GetVolumeInformation(drive, 0, 0, 0, 0, 0, fsname, 128))
                fsname[0] = 0;
            
            output(out, "%-10s %-8s ", drive, fsname);
            output(out, "%s ", llu_to_string(total.QuadPart / KiloByte));
            output(out, "%s ", llu_to_string((total.QuadPart - free_avail.QuadPart) / KiloByte));
            output(out, "%s ", llu_to_string(free_avail.QuadPart / KiloByte));
            output(out, "%3.0f%% ", perc_used);
            output(out, "%s\n", drive);
          }
      }
      drive += strlen(drive) + 1;
    }
}
 
 
void section_ps(SOCKET &out)
{
    output(out, "<<<ps>>>\n");
    HANDLE hProcessSnap;
    PROCESSENTRY32 pe32;
  
    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcessSnap != INVALID_HANDLE_VALUE) 
    {
      pe32.dwSize = sizeof(PROCESSENTRY32);
      if (Process32First(hProcessSnap, &pe32)) {
          do {
            output(out, "%s\n", pe32.szExeFile);
          } while (Process32Next(hProcessSnap, &pe32));
      }
      CloseHandle(hProcessSnap);
    }
}
 
 
void section_services(SOCKET &out)
{
    output(out, "<<<services>>>\n");
    SC_HANDLE scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
    if (scm != INVALID_HANDLE_VALUE) {
      DWORD bytes_needed = 0;
      DWORD num_services = 0;
      // first determine number of bytes needed
      EnumServicesStatusEx(scm, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, 
                       NULL, 0, &bytes_needed, &num_services, 0, 0);
      if (GetLastError() == ERROR_MORE_DATA && bytes_needed > 0) {
          BYTE *buffer = (BYTE *)malloc(bytes_needed);
          if (buffer) {
            if (EnumServicesStatusEx(scm, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, 
                               buffer, bytes_needed, 
                               &bytes_needed, &num_services, 0, 0))
            {
                ENUM_SERVICE_STATUS_PROCESS *service = (ENUM_SERVICE_STATUS_PROCESS *)buffer;
                for (unsigned i=0; i<num_services; i++) {
                  DWORD state = service->ServiceStatusProcess.dwCurrentState;
                  const char *state_name = "unknown";
                  switch (state) {
                  case SERVICE_CONTINUE_PENDING: state_name = "continuing"; break;
                  case SERVICE_PAUSE_PENDING:    state_name = "pausing"; break;
                  case SERVICE_PAUSED:           state_name = "paused"; break;
                  case SERVICE_RUNNING:          state_name = "running"; break;
                  case SERVICE_START_PENDING:    state_name = "starting"; break;
                  case SERVICE_STOP_PENDING:     state_name = "stopping"; break;
                  case SERVICE_STOPPED:          state_name = "stopped"; break;
                  }
 
                  // The service name usually does not contain spaces. But
                  // in some cases it does. We replace them with _ in order
                  // the keep it in one space-separated column. Since we own
                  // the buffer, we can simply change the name inplace.
                  for (char *w=(char *)(service->lpServiceName); *w; w++) {
                      if (*w == ' ')
                        *w = '_';
                  }                 
                  
                  output(out, "%-18s %-8s %s\n", 
                         service->lpServiceName, state_name,
                         service->lpDisplayName);
                  service ++;
                }
            }
            free(buffer);
          }
      }
      CloseServiceHandle(scm);
    }
}
 
#define DEFAULT_BUFFER_SIZE 40960L
 
// Hilfsfunktionen zum Navigieren in den Performance-Counter Binaerdaten
PERF_OBJECT_TYPE *FirstObject(PERF_DATA_BLOCK *dataBlock) { 
    return (PERF_OBJECT_TYPE *) ((BYTE *)dataBlock + dataBlock->HeaderLength); 
}
PERF_OBJECT_TYPE *NextObject(PERF_OBJECT_TYPE *act) {
    return (PERF_OBJECT_TYPE *) ((BYTE *)act + act->TotalByteLength); 
}
PERF_COUNTER_DEFINITION *FirstCounter(PERF_OBJECT_TYPE *perfObject) {
    return (PERF_COUNTER_DEFINITION *) ((BYTE *) perfObject + perfObject->HeaderLength); 
}
PERF_COUNTER_DEFINITION *NextCounter(PERF_COUNTER_DEFINITION *perfCounter) {
    return (PERF_COUNTER_DEFINITION *) ((BYTE *) perfCounter + perfCounter->ByteLength); 
}
PERF_COUNTER_BLOCK *GetCounterBlock(PERF_INSTANCE_DEFINITION *pInstance) {
    return (PERF_COUNTER_BLOCK *) ((BYTE *)pInstance + pInstance->ByteLength); 
}
PERF_INSTANCE_DEFINITION *FirstInstance (PERF_OBJECT_TYPE *pObject) {
    return (PERF_INSTANCE_DEFINITION *)  ((BYTE *) pObject + pObject->DefinitionLength); 
}
PERF_INSTANCE_DEFINITION *NextInstance (PERF_INSTANCE_DEFINITION *pInstance) {
    return (PERF_INSTANCE_DEFINITION *) ((BYTE *)pInstance + pInstance->ByteLength + GetCounterBlock(pInstance)->ByteLength); 
}
 
 
void dump_performance_counters(SOCKET &out, unsigned counter)
{
    // registry entry is ascii representation of counter index
    char counter_index_name[8];
    snprintf(counter_index_name, sizeof(counter_index_name), "%u", counter);
 
    // allocate block to store counter data block
    DWORD size = DEFAULT_BUFFER_SIZE;
    BYTE *data = new BYTE[DEFAULT_BUFFER_SIZE];
    DWORD type;
    DWORD ret;
 
    // Holt zu einem bestimmten Counter den kompletten Binärblock aus der
    // Registry. Da man vorher nicht weiß, wie groß der Puffer sein muss,
    // kann man nur mit irgendeiner Größe anfangen und dann diesen immer
    // wieder größer machen, wenn er noch zu klein ist. >:-P
    while ((ret = RegQueryValueEx(HKEY_PERFORMANCE_DATA, counter_index_name, 
                         0, &type, data, &size)) != ERROR_SUCCESS) 
    {
      if (ret == ERROR_MORE_DATA) // WIN32 API sucks...
      {
          // Der Puffer war zu klein. Toll. Also den Puffer größer machen
          // und das ganze nochmal probieren.
          size += DEFAULT_BUFFER_SIZE;
          debug("Buffer for RegQueryValueEx too small. Resizing...");
          delete [] data;
          data = new BYTE [size];
      } else {
          // Es ist ein anderer Fehler aufgetreten. Abbrechen.
          delete [] data;
          return;
      }
    }
 
    PERF_DATA_BLOCK *dataBlockPtr = (PERF_DATA_BLOCK *)data;
  
    // Determine first object in list of objects
    PERF_OBJECT_TYPE *objectPtr = FirstObject(dataBlockPtr);
  
    // Now walk through the list of objects. The bad news is:
    // even if we expect only one object, windows might send
    // us more that one object. We need to scan a list of objects
    // in order to find the one we have asked for. >:-P
    for (unsigned int a=0 ; a < dataBlockPtr->NumObjectTypes ; a++) 
    {
      // Have we found the object we seek? 
      if (objectPtr->ObjectNameTitleIndex == counter)
      {
          // Yes. Great. Now: each object consist of a lot of counters.
          // We walk through the list of counters in this object:
        
          // get pointer to first counter
          PERF_COUNTER_DEFINITION *counterPtr = FirstCounter(objectPtr);
 
          // Now we make a first quick walk through all counters, only in order
          // to find the beginning of the data block (which comes after the
          // counter definitions)
          PERF_COUNTER_DEFINITION *last_counter = FirstCounter(objectPtr);
          for(unsigned int b=0 ; b < objectPtr->NumCounters ; b++) 
            last_counter = NextCounter(last_counter);
          BYTE *datablock = (BYTE *)last_counter;
 
          // Now walk through the counter list a second time and output
          // all non-zero counters
          for(unsigned int b=0 ; b < objectPtr->NumCounters ; b++) 
          {
            outputCounter(out, datablock, counter, objectPtr, counterPtr);
            counterPtr = NextCounter(counterPtr);
          }
      }
      // naechstes Objekt in der Liste
      objectPtr = NextObject(objectPtr);
    }
    delete [] data;
}
 
 
void outputCounter(SOCKET &out, BYTE *datablock, int counter, 
               PERF_OBJECT_TYPE *objectPtr, PERF_COUNTER_DEFINITION *counterPtr)
{
    int num_instances = objectPtr->NumInstances;
    unsigned offset = counterPtr->CounterOffset;
    int size = counterPtr->CounterSize;
 
    // determine the type of the counter (for verbose output)
    const char *countertypename = "(unknown)";
    switch (counterPtr->CounterType) {
    case PERF_COUNTER_COUNTER:                countertypename = "counter"; break;
    case PERF_COUNTER_QUEUELEN_TYPE:          countertypename = "queuelen_type" ; break;
    case PERF_SAMPLE_COUNTER:                 countertypename = "sample_counter"; break;
//  case PERF_OBJ_TIME_TIMER:                 countertypename = "obj_time_timer"; break;
//  case PERF_COUNTER_100NS_QUEUELEN_TYPE:    countertypename = "100ns_queuelen_type"; break;
//  case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE: countertypename = "obj_time_queuelen_type"; break;
    case PERF_COUNTER_TIMER:                  countertypename = "timer"; break;
    case PERF_COUNTER_TIMER_INV:              countertypename = "timer_inv"; break;
    case PERF_COUNTER_BULK_COUNT:             countertypename = "bulk_count"; break;
//  case PERF_COUNTER_LARGE_QUEUELEN_TYPE:    countertypename = "large_queuelen_type"; break;
    case PERF_COUNTER_MULTI_TIMER:            countertypename = "multi_timer"; break;
    case PERF_COUNTER_MULTI_TIMER_INV:        countertypename = "multi_timer_inv"; break;
    case PERF_COUNTER_RAWCOUNT:               countertypename = "rawcount"; break;
    case PERF_COUNTER_RAWCOUNT_HEX:           countertypename = "rawcount_hex"; break;
//  case PERF_COUNTER_DELTA:                  countertypename = "delta"; break;
    case PERF_COUNTER_LARGE_RAWCOUNT:         countertypename = "large_rawcount"; break;
    case PERF_COUNTER_LARGE_RAWCOUNT_HEX:     countertypename = "large_rawcount_hex"; break;
//  case PERF_COUNTER_LARGE_DELTA:            countertypename = "large_delta"; break;
    case PERF_100NSEC_TIMER:                  countertypename = "100nsec_timer"; break;
    case PERF_100NSEC_TIMER_INV:              countertypename = "100nsec_timer_inv"; break;
    case PERF_100NSEC_MULTI_TIMER:            countertypename = "100nsec_multi_timer"; break;
    case PERF_100NSEC_MULTI_TIMER_INV:        countertypename = "100nsec_multi_timer_inv"; break;
    case PERF_SAMPLE_FRACTION:                countertypename = "sample_fraction"; break;
    case PERF_RAW_FRACTION:                   countertypename = "raw_fraction"; break;
//  case PERF_LARGE_RAW_FRACTION:             countertypename = "large_raw_fraction"; break;
//  case PERF_PRECISION_SYSTEM_TIMER:         countertypename = "precision_system_timer"; break;
//  case PERF_PRECISION_100NS_TIMER:          countertypename = "precision_100ns_timer"; break;
//  case PERF_PRECISION_OBJECT_TIMER:         countertypename = "precision_object_timer"; break;
    case PERF_AVERAGE_TIMER:                  countertypename = "average_timer"; break;
    case PERF_AVERAGE_BULK:                   countertypename = "average_bulk"; break;
    case PERF_SAMPLE_BASE:                countertypename = "sample_base"; break;
    case PERF_AVERAGE_BASE:               countertypename = "average_base"; break;
    case PERF_COUNTER_MULTI_BASE:         countertypename = "multi_base"; break;
    case PERF_RAW_BASE:                   countertypename = "raw_base"; break;
//  case PERF_LARGE_RAW_BASE:             countertypename = "large_raw_base"; break;
    case PERF_ELAPSED_TIME:               countertypename = "elapsed_time"; break;
    case PERF_COUNTER_TEXT:               countertypename = "text"; break;
    case PERF_COUNTER_NODATA:             countertypename = "nodata"; break;
    case PERF_COUNTER_HISTOGRAM_TYPE:         countertypename = "histogram_type"; break;
    }
            
    // Output index of counter object and counter, and timestamp
    output(out, "%d:%d %.2f", counter, counterPtr->CounterNameTitleIndex, current_time());
 
    // If this is a multi-instance-counter, loop over the instances
    if (num_instances >= 0) 
    {
      // get pointer to first instance
      PERF_INSTANCE_DEFINITION *instancePtr = FirstInstance(objectPtr);
              
      for(int b=0 ; b<objectPtr->NumInstances ; b++) 
      {
          // PERF_COUNTER_BLOCK dieser Instanz ermitteln.
          PERF_COUNTER_BLOCK *counterBlockPtr = GetCounterBlock(instancePtr);
          outputCounterValue(out, counterBlockPtr, size, offset);
          instancePtr = NextInstance(instancePtr);
      }
 
    }
    else { // instanceless counter
      PERF_COUNTER_BLOCK *counterBlockPtr = (PERF_COUNTER_BLOCK *) datablock;
      outputCounterValue(out, counterBlockPtr, size, offset);
    }
    output(out, " %s\n", countertypename);
}
 
 
void outputCounterValue(SOCKET &out, PERF_COUNTER_BLOCK *counterBlockPtr, int size, unsigned offset)
{
    if (size == 4) {
      DWORD value = *((DWORD *)((BYTE *)counterBlockPtr) + offset);
      output(out, " %lu", value);
    }
    else if (size == 8) {
      DWORD *data_at = (DWORD *)(((BYTE *)counterBlockPtr) + offset);
      DWORDLONG value = (DWORDLONG)*data_at + ((DWORDLONG)*(data_at + 1) << 32);
      output(out, " %s", llu_to_string(value));
    }
    else
      output(out, " unknown");
}
 
 
double current_time()
{
    SYSTEMTIME systime;
    FILETIME filetime;
    GetSystemTime(&systime);
    SystemTimeToFileTime(&systime, &filetime);
    unsigned long long ft = (unsigned long long)(filetime.dwLowDateTime)
      + (((unsigned long long)filetime.dwHighDateTime) << 32);
    return ft / 10000000.0;
}
 
 
void grow_eventlog_buffer(int newsize)
{
    delete [] eventlog_buffer;
    eventlog_buffer = new char[newsize];
    eventlog_buffer_size = newsize;
}
 
 
bool output_eventlog_entry(SOCKET &out, char *dllpath, EVENTLOGRECORD *event, char type_char, 
                     const char *logname, const char *source_name, char **strings)
{
    char msgbuffer[512];
    char dll_realpath[128];
    HINSTANCE dll;
 
    // if no dllpath is NULL, we output the message without text conversion and
    // always succeed. If a dll pathpath is given, we only succeed if the conversion
    // is successfull.
 
    if (dllpath) {
      // to make it even more difficult, dllpath may containt %SystemRoot%, which
      // must be replaced with the environment variable %SystemRoot% (most probably - 
      // but not entirely for sure - C:\WINDOWS
      if (strncasecmp(dllpath, "%SystemRoot%", 12) == 0)
          snprintf(dll_realpath, sizeof(dll_realpath), "%s%s", system_root(), dllpath + 12);
      else
          snprintf(dll_realpath, sizeof(dll_realpath), "%s", dllpath);
      
      // I found this path in the official API documentation. I hope
      // it's correct for all windows versions
      dll =  LoadLibrary(dll_realpath);
      if (!dll) {
          return false;
      }
    }
    else
      dll = NULL;
    
    DWORD len = FormatMessage(
      FORMAT_MESSAGE_ARGUMENT_ARRAY | 
      FORMAT_MESSAGE_FROM_HMODULE | 
      FORMAT_MESSAGE_FROM_SYSTEM,
      dll,                        
      event->EventID,                 
      0, // accept any language
      (LPTSTR)msgbuffer,         
      sizeof(msgbuffer),         
      strings);
    if (dll)
      FreeLibrary(dll);
    
    if (len == 0) {
      if (dllpath)
          return false;
      // if message cannot be converted than at least output the text strings
        msgbuffer[0] = 0;
      char *w = msgbuffer;
      int sizeleft = sizeof(msgbuffer) - 1;
      int n=0;
      while (strings[n]) {
          char *s = strings[n];
          int l = strlen(s);
          if (l < sizeleft) {
            strcpy(w, s);
            w += l;
            *w++ = ' ';
          }
          n++;
      }
      *w = 0;
    }
    
    // I'm not sure if Windows zero-terminates this if msg is too long...
    msgbuffer[sizeof(msgbuffer)-1] = 0; 
 
    // replace newlines with spaces. check_mk expects one message each line.
    char *w = msgbuffer;
    while (*w) {
      if (*w == '\n' || *w == '\r') *w = ' ';
      w++;
    }
    
    // convert UNIX timestamp to local time
    struct tm *t = localtime((time_t *)&event->TimeGenerated);
    char timestamp[64];
    strftime(timestamp, sizeof(timestamp), "%b %d %H:%M:%S", t);
    
    output(out, "%c %s %lu %s %s\n", type_char, timestamp,
         event->EventID, source_name, msgbuffer);
    return true;
}
 
 
void process_eventlog_entries(SOCKET &out, const char *logname, char *buffer, 
                        DWORD bytesread, DWORD *record_number, bool just_find_end,
                        int *worst_state)
{
    char *strings[64];
    char regpath[128];
    BYTE dllpath[128];
    char source_name[128];
 
    EVENTLOGRECORD *event = (EVENTLOGRECORD *)buffer;
    while (bytesread > 0) 
    {
      *record_number = event->RecordNumber;
      
      char type_char;
      int this_state;
      switch (event->EventType) {
      case EVENTLOG_ERROR_TYPE:
          type_char = 'C'; this_state = 2; break;
      case EVENTLOG_WARNING_TYPE:
          type_char = 'W'; this_state = 1; break;
      case EVENTLOG_INFORMATION_TYPE:
          type_char = '.'; this_state = 0; break;
      case EVENTLOG_AUDIT_SUCCESS:
          type_char = '.'; this_state = 0; break;
      case EVENTLOG_AUDIT_FAILURE:
          type_char = 'C'; this_state = 2; break;
      default:
          type_char = 'u'; this_state = 1; break;
      }
      if (*worst_state < this_state)
          *worst_state = this_state;
 
      if (!just_find_end) 
      {
          LPCTSTR lpSourceName = (LPCTSTR) ((LPBYTE) event + sizeof(EVENTLOGRECORD));
          
          // prepare source name without spaces (for check_mk output)
          strncpy(source_name, lpSourceName, sizeof(source_name));
          char *w = source_name;
          while (*w) {
            if (*w == ' ') *w = '_';
            *w++;
          }
          
          // prepare array of zero terminated strings to be inserted
          // into message template.
          DWORD num_strings = event->NumStrings;
          char *s = ((char *)event) + event->StringOffset;
          unsigned ns;
          for (ns = 0; ns < num_strings; ns++) {
            if (ns >= 63) break;
            strings[ns] = s;
            s += strlen(s) + 1;
          }
          strings[ns] = 0;
 
          
          // Windows eventlog entries refer to texts stored in a DLL >:-P
          // We need to load this DLL. First we need to look up which
          // DLL to load in the registry. Hard to image how one could
          // have contrieved this more complicated...
          snprintf(regpath, sizeof(regpath), 
                 "SYSTEM\\CurrentControlSet\\Services\\Eventlog\\%s\\%s",
                 logname, lpSourceName);
          DWORD size = sizeof(dllpath);
          HKEY key;
          DWORD ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0,
                             KEY_READ, &key);
 
          bool success = false;
          if (ret == ERROR_SUCCESS) 
          {
            if (ERROR_SUCCESS == RegQueryValueEx(key, "EventMessageFile", NULL, NULL, dllpath, &size))
            {
                // Answer may contain more than one DLL. They are separated
                // by semicola. Not knowing which one is the correct one, I try
                // all
                char *token = strtok((char *)dllpath, ";");
                while (token) {
                  if (output_eventlog_entry(out, token, event, type_char, logname, source_name, strings)) {
                      success = true;
                      break;
                  }
                  token = strtok(NULL, ";");
                }
            }
            RegCloseKey(key);
            }
            // No text conversion succeeded. Output without text anyway
            if (!success) {
            output_eventlog_entry(out, NULL, event, type_char, logname, source_name, strings);
        }
 
      } // type_char != '.'
          
      bytesread -= event->Length;
      event = (EVENTLOGRECORD *) ((LPBYTE) event + event->Length);
    }
}
 
 
void output_eventlog(SOCKET &out, const char *logname, 
                 DWORD *record_number, bool just_find_end)
{
    if (eventlog_buffer_size == 0) {
      const int initial_size = 65536;
      eventlog_buffer = new char[initial_size];
      eventlog_buffer_size = initial_size;
    }
 
    HANDLE hEventlog = OpenEventLog(NULL, logname);
    DWORD bytesread = 0;
    DWORD bytesneeded = 0;
    if (hEventlog) {
      output(out, "[[[%s]]]\n", logname);
      int worst_state = 0;
      DWORD old_record_number = *record_number;
 
      // we scan all new entries twice. At the first run we check if
      // at least one warning/error message is present. Only if this
      // is the case we make a second run where we output *all* messages,
      // even the informational once.
      for (int t=0; t<2; t++)
      {
          *record_number = old_record_number;
          verbose("Starting from entry number %u", old_record_number);
          while (true) {
            DWORD flags;
            if (*record_number == 0) {
                if (t == 1) {
                  verbose("Need to reopen Logfile in order to find start again.");
                  CloseEventLog(hEventlog);
                  hEventlog = OpenEventLog(NULL, logname);
                  if (!hEventlog) {
                      verbose("Failed to reopen event log. Bailing out.");
                      return;
                  }
                }
                flags = EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ;
            }
            else {
                verbose("Previous record number was %d. Doing seek read.", *record_number);
                flags = EVENTLOG_SEEK_READ | EVENTLOG_FORWARDS_READ;
            }
                
            if (ReadEventLog(hEventlog, 
                         flags,
                         *record_number + 1,
                         eventlog_buffer,
                         eventlog_buffer_size,
                         &bytesread,
                         &bytesneeded))
            {
                process_eventlog_entries(out, logname, eventlog_buffer, 
                                   bytesread, record_number, just_find_end || t==0, &worst_state);
            }
            else {
                DWORD error = GetLastError();
                if (error == ERROR_INSUFFICIENT_BUFFER) {
                  grow_eventlog_buffer(bytesneeded);
                }
                // found current end of log
                else if (error == ERROR_HANDLE_EOF) {
                  verbose("End of logfile reached at entry %u. Worst state is %d", 
                        *record_number, worst_state);
                  break;
                }
                // invalid parameter can also mean end of log
                else if (error == ERROR_INVALID_PARAMETER) {
                  verbose("Invalid parameter at entry %u (could mean end of logfile). Worst state is %d",
                        *record_number, worst_state);
                  break;
                }
                else {
                  output(out, "ERROR: Cannot read eventlog '%s': error %u\n", logname, error);
                  break;
                }
            }
          }
          if (worst_state == 0 && logwatch_suppress_info) {
            break; // nothing important found. Skip second run
          }
      }
      CloseEventLog(hEventlog);
    }
    else {
      output(out, "[[[%s:missing]]]\n", logname);
    }
}
 
 
// The output imitates that of the Linux agent. That makes
// a special check for check_mk unneccessary:
// <<<mem>>>.
// MemTotal:       514104 kB
// MemFree:         19068 kB
// SwapTotal:     1048568 kB
// SwapFree:      1043732 kB
 
void section_mem(SOCKET &out)
{
    output(out, "<<<mem>>>\n");
 
    MEMORYSTATUSEX statex;
    statex.dwLength = sizeof (statex);
    GlobalMemoryStatusEx (&statex);
 
    output(out, "MemTotal:  %11d kB\n", statex.ullTotalPhys / 1024);
    output(out, "MemFree:   %11d kB\n", statex.ullAvailPhys / 1024);
    output(out, "SwapTotal: %11d kB\n", (statex.ullTotalPageFile - statex.ullTotalPhys) / 1024);
    output(out, "SwapFree:  %11d kB\n", (statex.ullAvailPageFile - statex.ullAvailPhys) / 1024);
}
 
 
void section_winperf(SOCKET &out)
{
 
    output(out, "<<<winperf>>>\n");
  
    for (int i=0; i<700; i+=2) {
      if (i != 230 && i != 232 && i != 786 && i != 740)
          dump_performance_counters(out, i);
    }
}
 
 
// Keeps memory of an event log we have found. It
// might already be known and will not be stored twice.
void register_eventlog(char *logname)
{
    if (num_eventlogs >= MAX_EVENTLOGS)
      return; // veeery unlikely
 
    // check if we already know this one...
    for (unsigned i=0; i < num_eventlogs; i++) {
      if (!strcmp(logname, eventlog_names[i])) {
          newly_found[i] = true; // remember its still here
          return;
      }
    }
    
    // yet unknown. register it.
    known_record_numbers[num_eventlogs] = 0;
    eventlog_names[num_eventlogs] = strdup(logname); 
    newly_found[num_eventlogs] = true;
    num_eventlogs ++;
}
 
void unregister_all_eventlogs()
{
    for (unsigned i=0; i < num_eventlogs; i++)
      free(eventlog_names[i]);
    num_eventlogs = 0;
}
 
/* Look into the registry in order to find out, which
   event logs are available. */
bool find_eventlogs(SOCKET &out)
{
    for (unsigned i=0; i<num_eventlogs; i++)
      newly_found[i] = 0;
 
    char regpath[128];
    snprintf(regpath, sizeof(regpath), 
           "SYSTEM\\CurrentControlSet\\Services\\Eventlog");
    HKEY key;
    DWORD ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_ENUMERATE_SUB_KEYS, &key);
    
    bool success = true;
    if (ret == ERROR_SUCCESS) 
    {
      DWORD i = 0;
      char buffer[128];
      DWORD len;
      while (true) 
      {
          len = sizeof(buffer);
          DWORD r = RegEnumKeyEx(key, i, buffer, &len, NULL, NULL, NULL, NULL);
          if (r == ERROR_SUCCESS)
            register_eventlog(buffer);
          else if (r != ERROR_MORE_DATA)
          {
            if (r != ERROR_NO_MORE_ITEMS) {
                output(out, "ERROR: Cannot enumerate over event logs: error code %d\n", r);
                success = false;
            }
            break;
          }
          i ++;
      }
      RegCloseKey(key);
    }
    else {
      success = false;
      output(out, "ERROR: Cannot open registry key %s for enumeration: error code %d\n",
             regpath, GetLastError());
    }
    return success;
}
 
 
// The output of this section is compatible with
// the logwatch agent for Linux and UNIX
void section_eventlog(SOCKET &out)
{
    // This agent remembers the record numbers
    // of the event logs up to which messages have
    // been processed. When started, the eventlog
    // is skipped to the end. Historic messages are
    // not been processed. 
    static bool first_run = true;
 
    output(out, "<<<logwatch>>>\n");
    if (find_eventlogs(out))
    {
      for (unsigned i=0; i < num_eventlogs; i++) {
          if (!newly_found[i]) // not here any more!
            output(out, "[[[%s:missing]]]\n", eventlog_names[i]);
          else
            output_eventlog(out, eventlog_names[i], &known_record_numbers[i], 
                        first_run && !logwatch_send_initial_entries);
      }
    }
    first_run = false;
}
 
 
void output_data(SOCKET &out)
{
    output(out, "<<<check_mk>>>\n");
    output(out, "Version: %s\n", CHECK_MK_VERSION);
    section_df(out);
    section_ps(out);
    section_mem(out);
    section_services(out);
    section_winperf(out);
    section_eventlog(out);
}
    
 
void listen_tcp_loop()
{
    WSADATA wsa;
    if (0 != WSAStartup(MAKEWORD(2, 0), &wsa)) {
      fprintf(stderr, "Cannot initialize winsock.\n");
      exit(1);
    }
 
    SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
    if (s == INVALID_SOCKET) {
      fprintf(stderr, "Cannot create socket.\n");
      exit(1);
    }
    
    SOCKADDR_IN addr;
    memset(&addr, 0, sizeof(SOCKADDR_IN));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(CHECK_MK_AGENT_PORT);
    addr.sin_addr.s_addr = ADDR_ANY;
    
    if (SOCKET_ERROR == bind(s, (SOCKADDR *)&addr, sizeof(SOCKADDR_IN))) {
      fprintf(stderr, "Cannot bind socket to port %d\n", CHECK_MK_AGENT_PORT);
      exit(1);
    }
 
    if (SOCKET_ERROR == listen(s, 5)) {
      fprintf(stderr, "Cannot listen to socket\n");
      exit(1);
    }
 
    SOCKET connection;
    // Loop for ever.
    debug("Die Schleife gestartet.");
    while (!should_terminate) 
    {
      // Das Dreckswindows kann nicht vernuenftig gleichzeitig auf
      // ein Socket und auf ein Event warten. Weil ich nicht extra
      // deswegen mit Threads arbeiten will, verwende ich einfach 
      // select() mit einem Timeout und polle should_terminate.
 
      fd_set fds;
      FD_ZERO(&fds);
      FD_SET(s, &fds);
      struct timeval timeout;
      timeout.tv_sec = 0;
      timeout.tv_usec = 500000;
      if (1 == select(1, &fds, NULL, NULL, &timeout)) 
      {
          connection = accept(s, NULL, NULL);
          debug("Habe accepted.");
          if (connection != INVALID_SOCKET) {
 
            debug("socket ist auch da.");
            output_data(connection);
 
            closesocket(connection);
          }
      }
      else if (!should_terminate) {
          Sleep(1); // should never happen
      }
    }
    debug("Schleife beendet.");
    closesocket(s);
    WSACleanup();
}
 
void usage()
{
    fprintf(stderr, "Usage: \n"
          "check_mk_agent install -- install as Windows NT service Check_Mk_Agent\n"
          "check_mk_agent remove  -- remove Windows NT service\n"
          "check_mk_agent adhoc   -- open TCP port %d and answer request until killed\n"
          "check_mk_agent test    -- test output of plugin, do not open TCP port\n"
          "check_mk_agent debug   -- similar to test, but with lots of debug output\n", CHECK_MK_AGENT_PORT);
    exit(1);
}
 
 
 
// Zeugs fuer Windows Service
TCHAR*                gszServiceName = (TCHAR *)TEXT(SERVICE_NAME);
SERVICE_STATUS        serviceStatus;
SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
 
 
void WINAPI ServiceControlHandler( DWORD controlCode )
{
    switch ( controlCode )
    {
    case SERVICE_CONTROL_INTERROGATE:
      break;
 
    case SERVICE_CONTROL_SHUTDOWN:
    case SERVICE_CONTROL_STOP:
      should_terminate = true;
      serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
      SetServiceStatus( serviceStatusHandle, &serviceStatus );
      return;
 
    case SERVICE_CONTROL_PAUSE:
      break;
 
    case SERVICE_CONTROL_CONTINUE:
      break;
 
    default:
      if ( controlCode >= 128 && controlCode <= 255 )
          // user defined control code
          break;
      else
          // unrecognised control code
          break;
    }
 
    SetServiceStatus( serviceStatusHandle, &serviceStatus );
}
 
void WINAPI ServiceMain(DWORD, TCHAR* [] )
{
    // initialise service status
    serviceStatus.dwServiceType               = SERVICE_WIN32_OWN_PROCESS;
    serviceStatus.dwCurrentState              = SERVICE_STOPPED;
    serviceStatus.dwControlsAccepted          = 0;
    serviceStatus.dwWin32ExitCode             = NO_ERROR;
    serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
    serviceStatus.dwCheckPoint              = 0;
    serviceStatus.dwWaitHint                = 0;
    
    serviceStatusHandle = RegisterServiceCtrlHandler( gszServiceName,
                                          ServiceControlHandler );
 
    if ( serviceStatusHandle )
    {
      // service is starting
      serviceStatus.dwCurrentState = SERVICE_START_PENDING;
      SetServiceStatus( serviceStatusHandle, &serviceStatus );
 
      // Service running
      serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP |
                                   SERVICE_ACCEPT_SHUTDOWN);
      serviceStatus.dwCurrentState = SERVICE_RUNNING;
      SetServiceStatus( serviceStatusHandle, &serviceStatus );
 
      do_tcp = true;
      listen_tcp_loop();
 
      // service is now stopped
      serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP |
                                    SERVICE_ACCEPT_SHUTDOWN);
      serviceStatus.dwCurrentState = SERVICE_STOPPED;
      SetServiceStatus( serviceStatusHandle, &serviceStatus );
    }
}
 
void RunService()
{
    debug("Dienst aufgerufen!");
    SERVICE_TABLE_ENTRY serviceTable[] =
      {
          { gszServiceName, ServiceMain },
          { 0, 0 }
      };
    
    StartServiceCtrlDispatcher( serviceTable );
}
 
void InstallService()
{
    SC_HANDLE serviceControlManager = OpenSCManager( 0, 0,
                                         SC_MANAGER_CREATE_SERVICE );
 
    if ( serviceControlManager )
    {
      char path[ _MAX_PATH + 1 ];
      if ( GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0 )
      {
          SC_HANDLE service = CreateService( serviceControlManager,
                                     gszServiceName, gszServiceName,
                                     SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
                                     SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path,
                                     0, 0, 0, 0, 0 );
          if ( service )
          {
            CloseServiceHandle( service );
            printf(SERVICE_NAME " Installed Successfully\n");
          }
          else
          {
            if(GetLastError() == ERROR_SERVICE_EXISTS)
                printf(SERVICE_NAME " Already Exists.\n");
            else
                printf(SERVICE_NAME " Was not Installed Successfully. Error Code %d\n", (int)GetLastError());
          }
      }
 
      CloseServiceHandle( serviceControlManager );
    }
}
 
void UninstallService()
{
    SC_HANDLE serviceControlManager = OpenSCManager( 0, 0,
                                         SC_MANAGER_CONNECT );
 
    if ( serviceControlManager )
    {
      SC_HANDLE service = OpenService( serviceControlManager,
                               gszServiceName, SERVICE_QUERY_STATUS | DELETE );
      if ( service )
      {
          SERVICE_STATUS serviceStatus;
          if ( QueryServiceStatus( service, &serviceStatus ) )
          {
            if ( serviceStatus.dwCurrentState == SERVICE_STOPPED )
            {
                if(DeleteService( service ))
                  printf(SERVICE_NAME " Removed Successfully\n");
                else
                {
                  DWORD dwError;
                  dwError = GetLastError();
                  if(dwError == ERROR_ACCESS_DENIED)
                      printf("Access Denied While trying to Remove " SERVICE_NAME " \n");
                  else if(dwError == ERROR_INVALID_HANDLE)
                      printf("Handle invalid while trying to Remove " SERVICE_NAME " \n");
                  else if(dwError == ERROR_SERVICE_MARKED_FOR_DELETE)
                      printf(SERVICE_NAME " already marked for deletion\n");
                }
            }
            else
            {
                printf(SERVICE_NAME " is still Running.\n");
            }
          }
          CloseServiceHandle( service );
      }
      CloseServiceHandle( serviceControlManager );
    }
}
 
 
void do_test()
{
    do_tcp = false;
    SOCKET dummy;
    output_data(dummy);
}
 
 
void do_debug()
{
    verbose_mode = true;
    do_tcp = false;
    logwatch_send_initial_entries = true;
    logwatch_suppress_info = false;
    SOCKET dummy;
    find_eventlogs(dummy);
    //section_eventlog(dummy);
}
 
void do_adhoc()
{
    do_tcp = true;
    printf("Listening for TCP connections on port %d\n", CHECK_MK_AGENT_PORT);
    printf("Close window or press Ctrl-C to exit\n");
    fflush(stdout);
 
    should_terminate = false;
    listen_tcp_loop(); // runs for ever or until Ctrl-C
}
 
void do_install()
{
    InstallService();
}
 
void do_remove()
{
    UninstallService();
}
 
void cleanup()
{
    if (eventlog_buffer_size > 0)
      delete [] eventlog_buffer;
    unregister_all_eventlogs(); // frees a few bytes
}
 
 
int main(int argc, char **argv)
{
    if (argc > 2)
      usage();
    else if (argc <= 1)
      RunService();
    else if (!strcmp(argv[1], "test"))
      do_test();
    else if (!strcmp(argv[1], "adhoc"))
      do_adhoc();
    else if (!strcmp(argv[1], "install"))
      do_install();
    else if (!strcmp(argv[1], "remove"))
      do_remove();
    else if (!strcmp(argv[1], "debug"))
      do_debug();
    else
      usage();
 
    cleanup();
}
[+][-]10/23/09 04:17 AM, ID: 25643241Expert Comment

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 30-day free trial to view this Expert Comment or ask the Experts your question.

 
[+][-]10/23/09 05:13 AM, ID: 25643585Author Comment

Often, when Experts are collaborating with members who have asked questions, they will request additional information about the problem. Askers respond with an author comment like this one.

Start your 30-day free trial to view this Author Comment or ask the Experts your question.

 
[+][-]10/23/09 05:18 AM, ID: 25643616Expert Comment

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 30-day free trial to view this Expert Comment or ask the Experts your question.

 
[+][-]10/23/09 05:43 AM, ID: 25643779Expert Comment

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 30-day free trial to view this Expert Comment or ask the Experts your question.

 
[+][-]10/24/09 02:17 AM, ID: 25651390Author Comment

Often, when Experts are collaborating with members who have asked questions, they will request additional information about the problem. Askers respond with an author comment like this one.

Start your 30-day free trial to view this Author Comment or ask the Experts your question.

 
[+][-]10/24/09 07:10 AM, ID: 25652272Expert Comment

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 30-day free trial to view this Expert Comment or ask the Experts your question.

 
[+][-]10/25/09 06:11 AM, ID: 25656518Author Comment

Often, when Experts are collaborating with members who have asked questions, they will request additional information about the problem. Askers respond with an author comment like this one.

Start your 30-day free trial to view this Author Comment or ask the Experts your question.

 
[+][-]10/26/09 05:44 AM, ID: 25661644Expert Comment

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 30-day free trial to view this Expert Comment or ask the Experts your question.

 
[+][-]10/26/09 05:53 AM, ID: 25661716Expert Comment

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 30-day free trial to view this Expert Comment or ask the Experts your question.

 
[+][-]10/29/09 05:02 AM, ID: 25692642Author Comment

Often, when Experts are collaborating with members who have asked questions, they will request additional information about the problem. Askers respond with an author comment like this one.

Start your 30-day free trial to view this Author Comment or ask the Experts your question.

 
[+][-]10/29/09 05:05 AM, ID: 25692662Author Comment

Often, when Experts are collaborating with members who have asked questions, they will request additional information about the problem. Askers respond with an author comment like this one.

Start your 30-day free trial to view this Author Comment or ask the Experts your question.

 
[+][-]10/29/09 05:31 PM, ID: 25699407Expert Comment

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 30-day free trial to view this Expert Comment or ask the Experts your question.

 
 
Loading Advertisement...
20091111-EE-VQP-92 - Hierarchy / EE_QW_3_20080625