summaryrefslogtreecommitdiffstats
path: root/private/sdktools/perflog
diff options
context:
space:
mode:
Diffstat (limited to 'private/sdktools/perflog')
-rw-r--r--private/sdktools/perflog/dirs2
-rw-r--r--private/sdktools/perflog/pdlcnfig/common.h121
-rw-r--r--private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.cnt6
-rw-r--r--private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.hlpbin0 -> 11923 bytes
-rw-r--r--private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.hm17
-rw-r--r--private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.hpj66
-rw-r--r--private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.ph110
-rw-r--r--private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.rtf117
-rw-r--r--private/sdktools/perflog/pdlcnfig/makefile6
-rw-r--r--private/sdktools/perflog/pdlcnfig/makefile.inc10
-rw-r--r--private/sdktools/perflog/pdlcnfig/makehelp.bat26
-rw-r--r--private/sdktools/perflog/pdlcnfig/outpage.cpp926
-rw-r--r--private/sdktools/perflog/pdlcnfig/outpage.h68
-rw-r--r--private/sdktools/perflog/pdlcnfig/pdlcnfig.cpp360
-rw-r--r--private/sdktools/perflog/pdlcnfig/pdlcnfig.h47
-rw-r--r--private/sdktools/perflog/pdlcnfig/pdlcnfig.icobin0 -> 1078 bytes
-rw-r--r--private/sdktools/perflog/pdlcnfig/pdlcnfig.rc457
-rw-r--r--private/sdktools/perflog/pdlcnfig/resource.h113
-rw-r--r--private/sdktools/perflog/pdlcnfig/setpage.cpp974
-rw-r--r--private/sdktools/perflog/pdlcnfig/setpage.h75
-rw-r--r--private/sdktools/perflog/pdlcnfig/sources62
-rw-r--r--private/sdktools/perflog/pdlcnfig/stdafx.cpp7
-rw-r--r--private/sdktools/perflog/pdlcnfig/stdafx.h15
-rw-r--r--private/sdktools/perflog/pdlsvc/logthred.c644
-rw-r--r--private/sdktools/perflog/pdlsvc/logutils.c914
-rw-r--r--private/sdktools/perflog/pdlsvc/logutils.h36
-rw-r--r--private/sdktools/perflog/pdlsvc/makefile6
-rw-r--r--private/sdktools/perflog/pdlsvc/makefile.inc10
-rw-r--r--private/sdktools/perflog/pdlsvc/pdlmsg.mc131
-rw-r--r--private/sdktools/perflog/pdlsvc/pdlsvc.c392
-rw-r--r--private/sdktools/perflog/pdlsvc/pdlsvc.h69
-rw-r--r--private/sdktools/perflog/pdlsvc/pdlsvc.rc12
-rw-r--r--private/sdktools/perflog/pdlsvc/sources50
33 files changed, 5849 insertions, 0 deletions
diff --git a/private/sdktools/perflog/dirs b/private/sdktools/perflog/dirs
new file mode 100644
index 000000000..b156685a4
--- /dev/null
+++ b/private/sdktools/perflog/dirs
@@ -0,0 +1,2 @@
+DIRS=pdlcnfig pdlsvc
+ \ No newline at end of file
diff --git a/private/sdktools/perflog/pdlcnfig/common.h b/private/sdktools/perflog/pdlcnfig/common.h
new file mode 100644
index 000000000..febd186d8
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/common.h
@@ -0,0 +1,121 @@
+/*
+ Performance Logging Service common definitions file
+*/
+
+#ifndef _PERFLOG_COMMON_H_
+#define _PERFLOG_COMMON_H_
+
+// common definitions
+
+#if UNICODE
+#define _ultot _ultow
+#define _ltot _ltow
+#else // not UNICODE
+#define _ultot _ultoa
+#define _ltot _ltoa
+#endif
+
+// output file configuration definitions
+
+#define OPD_CSV_FILE 0
+#define OPD_TSV_FILE 1
+#define OPD_BIN_FILE 2
+#define OPD_NUM_FILE_TYPES 3
+
+#define OPD_NAME_MMDDHH 0
+#define OPD_NAME_NNNNNN 1
+#define OPD_NAME_YYDDD 2
+#define OPD_NAME_YYMM 3
+#define OPD_NAME_YYMMDD 4
+#define OPD_NAME_YYMMDDHH 5
+
+#define OPD_RENAME_HOURS 0
+#define OPD_RENAME_DAYS 1
+#define OPD_RENAME_MONTHS 2
+#define OPD_RENAME_KBYTES 3
+#define OPD_RENAME_MBYTES 4
+
+// settings page
+
+// sample interval units combo box settings
+#define SIU_SECONDS 0
+#define SIU_MINUTES 1
+#define SIU_HOURS 2
+#define SIU_DAYS 3
+
+#define SECONDS_IN_DAY 86400
+#define SECONDS_IN_HOUR 3600
+#define SECONDS_IN_MINUTE 60
+
+#define LOG_SERV_START 1
+#define LOG_SERV_STOP 2
+#define LOG_SERV_PAUSE 4
+#define LOG_SERV_RESUME 8
+
+// alarm configuration and setting information
+
+// alarm configuration flags
+
+#define ALERT_FLAGS_OVER_THRESHOLD (DWORD)0x00000001
+#define ALERT_FLAGS_UNDER_THRESHOLD (DWORD)0x00000002
+#define ALERT_FLAGS_THRESHOLD_MASK (DWORD)0x00000003
+
+#define ALERT_FLAGS_EXECUTE_PROGRAM (DWORD)0x00000010
+#define ALERT_FLAGS_TEXT_LOG (DWORD)0x00000020
+#define ALERT_FLAGS_EVENT_LOG (DWORD)0x00000040
+#define ALERT_FLAGS_NET_MESSAGE (DWORD)0x00000080
+
+#define ALERT_FLAGS_FIRST_TIME (DWORD)0x00000100
+#define ALERT_FLAGS_EVERY_TIME (DWORD)0x00000200
+
+#define ALERT_FLAGS_NAME_PARAM (DWORD)0x00001000
+#define ALERT_FLAGS_VALUE_PARAM (DWORD)0x00002000
+#define ALERT_FLAGS_THRESHOLD_PARAM (DWORD)0x00004000
+#define ALERT_FLAGS_TIME_PARAM (DWORD)0x00008000
+
+#define ALERT_FLAGS_INFO (DWORD)0x00010000
+#define ALERT_FLAGS_WARNING (DWORD)0x00020000
+#define ALERT_FLAGS_ERROR (DWORD)0x00030000
+#define ALERT_FLAGS_SEVERITY_SHIFT (DWORD)16L
+#define ALERT_FLAGS_SEVERITY_MASK (DWORD)0x00030000
+
+#define ALERT_FLAGS_DELETE (DWORD)0x40000000
+#define ALERT_FLAGS_ALERTED (DWORD)0x80000000
+
+typedef struct _ALERT_CONFIG_INFO_W {
+ DWORD dwTotalSize;
+ HKEY hKeyCounter;
+ LONG lEditIndex;
+ LPWSTR szCounterPath;
+ LPWSTR szCommandLine;
+ LPWSTR szNetName;
+ DWORD dwAlertFlags;
+ DWORD dwThresholdValue;
+} ALERT_CONFIG_INFO_W, FAR * LPALERT_CONFIG_INFO_W;
+
+typedef struct _ALERT_CONFIG_INFO_A {
+ DWORD dwTotalSize;
+ HKEY hKeyCounter;
+ LONG lEditIndex;
+ LPSTR szCounterPath;
+ LPSTR szCommandLine;
+ LPSTR szNetName;
+ DWORD dwAlertFlags;
+ DWORD dwThresholdValue;
+} ALERT_CONFIG_INFO_A, FAR * LPALERT_CONFIG_INFO_A;
+
+#ifdef UNICODE
+#define ALERT_CONFIG_INFO ALERT_CONFIG_INFO_W
+#define LPALERT_CONFIG_INFO LPALERT_CONFIG_INFO_W
+#else
+#define ALERT_CONFIG_INFO ALERT_CONFIG_INFO_A
+#define LPALERT_CONFIG_INFO LPALERT_CONFIG_INFO_A
+#endif
+
+#define KEY_BS_CHAR TEXT('|')
+#define BS_CHAR TEXT('\\')
+#define KEY_GT_CHAR TEXT('>')
+#define KEY_LT_CHAR TEXT('<')
+
+#endif //_PERFLOG_COMMON_H_
+
diff --git a/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.cnt b/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.cnt
new file mode 100644
index 000000000..afec206c1
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.cnt
@@ -0,0 +1,6 @@
+:Base pdlcnfig.hlp
+1 Perf Data Log Service
+2 Overview=HIDD_PDLCNFIG_DIALOG
+2 Log Settings=HIDD_SETTINGS_PAGE
+2 Log File=HIDD_OUTPUT_PAGE
+ \ No newline at end of file
diff --git a/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.hlp b/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.hlp
new file mode 100644
index 000000000..ee941129f
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.hlp
Binary files differ
diff --git a/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.hm b/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.hm
new file mode 100644
index 000000000..a575e498b
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.hm
@@ -0,0 +1,17 @@
+// MAKEHELP.BAT generated Help Map file. Used by pdlcnfig.HPJ.
+
+// Commands (ID_* and IDM_*)
+HIDM_ABOUTBOX 0x10010
+
+// Prompts (IDP_*)
+
+// Resources (IDR_*)
+HIDR_MAINFRAME 0x203E8
+
+// Dialogs (IDD_*)
+HIDD_ABOUTBOX 0x20064
+HIDD_PDLCNFIG_DIALOG 0x20065
+HIDD_SETTINGS_PAGE 0x20066
+HIDD_OUTPUT_PAGE 0x20067
+
+// Frame Controls (IDW_*)
diff --git a/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.hpj b/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.hpj
new file mode 100644
index 000000000..5382ab795
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.hpj
@@ -0,0 +1,66 @@
+; This file is maintained by HCW. Do not modify this file directly.
+
+[OPTIONS]
+HCW=0
+COMPRESS=12 Hall Zeck
+LCID=0x409 0x0 0x0 ;English (United States)
+REPORT=Yes
+FTS=1
+CONTENTS=HIDD_PDLCNFIG_DIALOG
+TITLE=Perf Data Log Configuration Application Help
+CNT=pdlcnfig.cnt
+COPYRIGHT=Perf Data Log Copyright (c) 1996 Microsoft Corporation
+CITATION=Perf Data Log Copyright (c) 1996 Microsoft Corporation
+BMROOT=..
+BMROOT=.
+ROOT=..
+ROOT=.
+HLP=.\Pdlcnfig.hlp
+
+[FILES]
+pdlcnfig.rtf
+
+[ALIAS]
+HIDD_ABOUTBOX = HID_APP_ABOUT
+HID_HT_SIZE = HID_SC_SIZE
+HID_HT_HSCROLL = scrollbars
+HID_HT_VSCROLL = scrollbars
+HID_HT_MINBUTTON = HID_SC_MINIMIZE
+HID_HT_MAXBUTTON = HID_SC_MAXIMIZE
+AFX_HIDP_INVALID_FILENAME = AFX_HIDP_default
+AFX_HIDP_FAILED_TO_OPEN_DOC = AFX_HIDP_default
+AFX_HIDP_FAILED_TO_SAVE_DOC = AFX_HIDP_default
+AFX_HIDP_ASK_TO_SAVE = AFX_HIDP_default
+AFX_HIDP_FAILED_TO_CREATE_DOC = AFX_HIDP_default
+AFX_HIDP_FILE_TOO_LARGE = AFX_HIDP_default
+AFX_HIDP_FAILED_TO_START_PRINT = AFX_HIDP_default
+AFX_HIDP_FAILED_TO_LAUNCH_HELP = AFX_HIDP_default
+AFX_HIDP_INTERNAL_FAILURE = AFX_HIDP_default
+AFX_HIDP_COMMAND_FAILURE = AFX_HIDP_default
+AFX_HIDP_PARSE_INT = AFX_HIDP_default
+AFX_HIDP_PARSE_REAL = AFX_HIDP_default
+AFX_HIDP_PARSE_INT_RANGE = AFX_HIDP_default
+AFX_HIDP_PARSE_REAL_RANGE = AFX_HIDP_default
+AFX_HIDP_PARSE_STRING_SIZE = AFX_HIDP_default
+AFX_HIDP_FAILED_INVALID_FORMAT = AFX_HIDP_default
+AFX_HIDP_FAILED_INVALID_PATH = AFX_HIDP_default
+AFX_HIDP_FAILED_DISK_FULL = AFX_HIDP_default
+AFX_HIDP_FAILED_ACCESS_READ = AFX_HIDP_default
+AFX_HIDP_FAILED_ACCESS_WRITE = AFX_HIDP_default
+AFX_HIDP_FAILED_IO_ERROR_READ = AFX_HIDP_default
+AFX_HIDP_FAILED_IO_ERROR_WRITE = AFX_HIDP_default
+AFX_HIDP_STATIC_OBJECT = AFX_HIDP_default
+AFX_HIDP_FAILED_TO_CONNECT = AFX_HIDP_default
+AFX_HIDP_SERVER_BUSY = AFX_HIDP_default
+AFX_HIDP_BAD_VERB = AFX_HIDP_default
+AFX_HIDP_FAILED_MEMORY_ALLOC = AFX_HIDP_default
+AFX_HIDP_FAILED_TO_NOTIFY = AFX_HIDP_default
+AFX_HIDP_FAILED_TO_LAUNCH = AFX_HIDP_default
+AFX_HIDP_ASK_TO_UPDATE = AFX_HIDP_default
+AFX_HIDP_FAILED_TO_UPDATE = AFX_HIDP_default
+AFX_HIDP_FAILED_TO_REGISTER = AFX_HIDP_default
+AFX_HIDP_FAILED_TO_AUTO_REGISTER = AFX_HIDP_default
+
+[MAP]
+#include <d:\MSVC40\MFC\include\afxhelp.hm>
+#include <pdlcnfig.hm>
diff --git a/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.ph b/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.ph
new file mode 100644
index 000000000..d90408241
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.ph
@@ -0,0 +1,110 @@
+Assignment
+Collection
+Configuration
+Data
+Filename
+Log
+Log Settings
+Manual
+Perf
+Remove
+Separated
+Settings
+Variable
+Windows
+and
+application
+applications.
+are
+automatic
+automatically
+base
+box
+box.
+browser
+button
+buttons
+can
+cause
+collected
+common
+configure
+configured
+consists
+control
+controlled
+controls
+counter
+counters
+created
+current
+currently
+database
+describe
+dialog
+digits
+directory
+displayed
+edit
+enabled
+example
+file
+files
+folder
+following
+for
+format
+from
+generated
+interval
+list
+logging
+manipulation
+manually.
+name
+number
+operation
+output
+page
+pages
+performance
+periodically.
+possible
+program
+property
+push
+radio
+renamed
+renaming
+running.
+sample
+select
+selected
+selected,
+sequence
+service
+service.
+services
+should
+specified
+specify
+start
+started
+stop
+stopped
+string
+system
+that
+the
+then
+there
+this
+time
+two
+used
+using
+utility
+values
+when
+will
+written
diff --git a/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.rtf b/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.rtf
new file mode 100644
index 000000000..56dcbee8f
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/hlp/pdlcnfig.rtf
@@ -0,0 +1,117 @@
+{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f2\fswiss\fcharset0\fprq2 Helv{\*\falt Arial};}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f5\fswiss\fcharset0\fprq2 Arial;}
+{\f7\fswiss\fcharset0\fprq2 MS Sans Serif;}{\f9\fswiss\fcharset0\fprq2 Helvetica;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;
+\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{\nowidctlpar \f4\fs20 \snext0
+Normal;}{\s1\sb240\nowidctlpar \b\f2\ul \sbasedon0\snext0 heading 1;}{\s2\sb120\nowidctlpar \b\f2 \sbasedon0\snext0 heading 2;}{\s3\li360\nowidctlpar \b\f4 \sbasedon0\snext17 heading 3;}{\s4\li360\nowidctlpar \f4\ul \sbasedon0\snext17 heading 4;}{
+\s5\li720\nowidctlpar \b\f4\fs20 \sbasedon0\snext17 heading 5;}{\s6\li720\nowidctlpar \f4\fs20\ul \sbasedon0\snext17 heading 6;}{\s7\li720\nowidctlpar \i\f4\fs20 \sbasedon0\snext17 heading 7;}{\s8\li720\nowidctlpar \i\f4\fs20 \sbasedon0\snext17
+heading 8;}{\s9\li720\nowidctlpar \i\f4\fs20 \sbasedon0\snext17 heading 9;}{\*\cs10 \additive Default Paragraph Font;}{\*\cs15 \additive\fs16\up6\lang1033 \sbasedon10 footnote reference;}{\s16\nowidctlpar \f4\fs20 \sbasedon0\snext16 footnote text;}{
+\s17\li720\nowidctlpar \f4\fs20 \sbasedon0\snext17 Normal Indent;}{\s18\fi-240\li480\sb80\nowidctlpar\tx480 \f9 \sbasedon0\snext18 nscba;}{\s19\fi-240\li240\sa20\nowidctlpar \f9 \sbasedon0\snext19 j;}{\s20\li480\sa20\nowidctlpar \f9 \sbasedon0\snext20
+ij;}{\s21\sb80\sa20\nowidctlpar \f9 \sbasedon0\snext21 btb;}{\s22\fi-240\li2400\sb20\sa20\nowidctlpar \f9\fs20 \sbasedon0\snext22 ctcb;}{\s23\fi-240\li480\sa40\nowidctlpar\tx480 \f9 \sbasedon0\snext23 ns;}{\s24\sa120\nowidctlpar \f9\fs28
+\sbasedon0\snext24 TT;}{\s25\fi-240\li2400\sa20\nowidctlpar \f9 \sbasedon0\snext25 crtj;}{\s26\fi-240\li480\nowidctlpar\tx480 \f9 \sbasedon0\snext26 nsca;}{\s27\sa20\nowidctlpar \f9 \sbasedon0\snext27 bt;}{\s28\li240\sb120\sa40\nowidctlpar \f9
+\sbasedon0\snext28 Hf;}{\s29\li240\sb120\sa40\nowidctlpar \f9 \sbasedon0\snext29 Hs;}{\s30\li480\sb120\sa40\nowidctlpar \f9 \sbasedon0\snext30 RT;}{\s31\fi-2160\li2160\sb240\sa80\nowidctlpar\tx2160 \f9 \sbasedon0\snext31 c;}{\s32\li2160\sa20\nowidctlpar
+\f9 \sbasedon0\snext32 ct;}{\s33\li240\sa20\nowidctlpar \f9 \sbasedon0\snext33 it;}{\s34\li480\nowidctlpar \f9\fs20 \sbasedon0\snext34 nsct;}{\s35\fi-160\li400\sb80\sa40\nowidctlpar \f9 \sbasedon0\snext35 nscb;}{\s36\fi-2640\li2880\sb120\sa40\nowidctlpar
+\brdrb\brdrs\brdrw15 \brdrbtw\brdrs\brdrw15 \tx2880 \f9 \sbasedon0\snext36 HC2;}{\s37\fi-2640\li2880\sb120\sa20\nowidctlpar\tx2880 \f9 \sbasedon0\snext37 C2;}{\s38\fi-240\li2400\sa20\nowidctlpar \f9\fs20 \sbasedon0\snext38 ctc;}{
+\s39\li2160\sb160\nowidctlpar \f9 \sbasedon0\snext39 crt;}{\s40\li480\sb20\sa40\nowidctlpar \f9 \sbasedon0\snext40 or;}{\s41\fi-259\li360\sb40\sa40\nowidctlpar\tx360 \f7\fs20 \sbasedon0\snext41 Ln1;}{\s42\li115\sb80\sa80\nowidctlpar \f7\fs20
+\sbasedon0\snext0 *Intro;}{\s43\li115\sb80\sa80\keepn\nowidctlpar \b\f7 \sbasedon3\snext42 *Title;}{\s44\fi-245\li360\sb80\nowidctlpar \f7\fs20 \snext44 *Jl;}{\s45\li360\sb40\sa40\nowidctlpar \f7\fs20 \snext0 Lp1;}{\s46\fi-1800\li1915\sb60\sl-240\slmult0
+\nowidctlpar\tx1915 \f7\fs20 \sbasedon0\snext46 Tph;}{\s47\li115\sb120\sa80\nowidctlpar \b\f7\fs20 \snext41 Proch;}{\*\cs48 \additive\super \sbasedon10 endnote reference;}}{\info{\author David Broman}{\operator Bob Watson}
+{\creatim\yr1993\mo11\dy4\hr18\min38}{\revtim\yr1996\mo7\dy23\hr15\min9}{\version2}{\edmins1}{\nofpages4}{\nofwords1071}{\nofchars6106}{\*\company Microsoft}{\vern57431}}\widowctrl\ftnbj\aenddoc\makebackup\hyphcaps0 \fet0\sectd \linex0\endnhere
+{\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5
+\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang
+{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard\plain \s1\sb240\nowidctlpar \b\f2\ul {\cs15\f5\fs16\up6 #{\footnote \pard\plain \sl240\slmult0\widctlpar \f4\fs20 {\cs15\b\fs16\up6 #} HIDD_PDLCNFIG_DIALOG
+}}{\f5\fs16 }{\f5 Perf Data Log Overview
+\par }\pard\plain \sl240\slmult0\widctlpar \f4\fs20 {\f5\up6 The Perf Data Log utility consists of two components:
+\par {\pntext\pard\plain\f1\fs20\up6 \'b7\tab}}\pard \fi-360\li360\sl240\slmult0\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}{\f5\up6 The }{\b\f5\up6 Configuration}{\f5\up6 property pages
+\par {\pntext\pard\plain\f1\fs20 \'b7\tab}The }{\b\f5\up6 Data Collection}{\f5\up6 service}{\f5
+\par }\pard \sl240\slmult0\widctlpar {\f5 The configuration property pages are used to configure the operation of the data collection service. The data collection services can also be started and stopped by the configuration property pages as well.
+\par }\pard\plain \s2\sb120\nowidctlpar \b\f2 {\f5 Features
+\par }\pard\plain \nowidctlpar \f4\fs20 {\f5
+The Perf Data Log utility is a service that runs in the background on a Windows NT system to monitor and record performance data of selected system parameters. The performance data is recorded in a text format for easy manipulation by common database and
+spreadsheet applications. Since the utility runs as a service it can be started automatically when the system is started or controlled manually. The log files created by the service can be renamed periodically for subsequent manipulation or archiving.
+
+\par
+\par }\pard\plain \s2\sb120\nowidctlpar \b\f2 {\f5 Installation
+\par }\pard\plain \sl240\slmult0\widctlpar \f4\fs20 {\f5 The Perf Data Log service is installed by copying the following files the SYSTEM32 directory in the WINDOWS NT root directory.
+\par {\pntext\pard\plain\b\f1\fs20 \'b7\tab}}\pard \fi-360\li1080\sl240\slmult0\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}{\b\f5 PDLCNFIG.EXE}{\f5 \endash The configuration program}{\b\f5
+\par {\pntext\pard\plain\b\f1\fs20 \'b7\tab}PDLCNFIG.HLP}{\f5 \endash The configuration program help file}{\b\f5
+\par {\pntext\pard\plain\b\f1\fs20 \'b7\tab}PDLCNFIG.CNT}{\f5 \endash The configuration program contents file}{\b\f5
+\par {\pntext\pard\plain\b\f1\fs20 \'b7\tab}PDLSVC.EXE }{\f5 \endash The data collection service}{\b\f5
+\par {\pntext\pard\plain\b\f1\fs20 \'b7\tab}PDH.DLL }{\f5 \endash The performance data interface library}{\b\f5
+\par }\pard \sl240\slmult0\widctlpar {\f5 Once all these files are in place, the configuration program will install the service the first time it is run on the system.}{\b\f5
+\par }\pard\plain \s2\sb120\nowidctlpar \b\f2 {\f5 Configuration
+\par }\pard\plain \nowidctlpar \f4\fs20 {\f5 Before the data collection service can start logging data it must be configured using the Configuration property pages. The Configuration property pages are in the PDLCNFIG application program.
+\par }\pard\plain \s3\li360\nowidctlpar \b\f4 {\f5 Log Settings
+\par }\pard\plain \s17\li720\nowidctlpar \f4\fs20 {\f5
+The Log Settings property page is used to select the performance counters to log and the interval between data samples. The service can also be started, stopped and set to automatic using this property page.
+\par }\pard\plain \s3\li360\nowidctlpar \b\f4 {\f5 Log Files
+\par }\pard\plain \s17\li720\nowidctlpar \f4\fs20 {\f5 This property page is used to configure how the data will be written. The output file can be named specifically, or it can be renamed periodically.
+\par }\pard\plain \s2\sb120\nowidctlpar \b\f2 {\f5 Operation
+\par }\pard\plain \nowidctlpar \f4\fs20 {\f5
+Once the service has been configured, it can be started by either selecting the Start button on the Log Settings page, or the service can be set to start automatically the next time the system is restarted. The data files generated by the service can be v
+iewed while the service is running, so long as they are not locked, preventing possible updates by the service. If this may be a problem, then the service should be stopped while the files are read or copied.
+\par }\pard\plain \s2\sb120\nowidctlpar \b\f2 {\f5 Using the Data
+\par }\pard\plain \nowidctlpar \f4\fs20 {\f5
+The data from the data files is stored in a common text data format and may be imported into spreadsheet or database applications. (Microsoft Excel or Access, for example). Once in the database, the user may manipulate the data as desired.
+\par }\pard\plain \s1\sb240\nowidctlpar \b\f2\ul {\f5 \page }{\cs15\f5\fs16\up6 #{\footnote \pard\plain \s16\nowidctlpar \f4\fs20 {\cs15\fs16\up6 #} HIDD_SETTINGS_PAGE}}{\f5 Log Settings
+\par }\pard\plain \nowidctlpar \f4\fs20 {\f5 The Log Settings property page is used to configure the counters to be logged, the sample interval and the status of the logging service.
+\par }\pard\plain \s2\sb120\nowidctlpar \b\f2 {\f5 Service Start
+\par }\pard\plain \nowidctlpar \f4\fs20 {\f5 The buttons in this group control the data collection service.
+\par }\pard\plain \s3\li360\nowidctlpar \b\f4 {\f5 Automatic
+\par }\pard\plain \s17\li720\nowidctlpar \f4\fs20 {\f5 Select this radio button to cause the service to start automatically each time the system is restarted
+\par }\pard\plain \s3\li360\nowidctlpar \b\f4 {\f5 Manual
+\par }\pard\plain \s17\li720\nowidctlpar \f4\fs20 {\f5 Select this radio button to cause the service to start and stop manually. The service can be controlled by the Start and Stop buttons in this group box or by the Services Control Panel applet.
+\par }\pard\plain \s3\li360\nowidctlpar \b\f4 {\f5 Start
+\par }\pard\plain \s17\li720\nowidctlpar \f4\fs20 {\f5 Select this button to start the data collection service. This button is only enabled when the Manual radio button is selected and the service is not currently running.
+\par }\pard\plain \s3\li360\nowidctlpar \b\f4 {\f5 Stop
+\par }\pard\plain \s17\li720\nowidctlpar \f4\fs20 {\f5 Select this button to stop the data collection service. This button is only enabled when the Manual radio button is selected and the service is currently running.
+\par }\pard\plain \s2\sb120\nowidctlpar \b\f2 {\f5 Sample Interval
+\par }\pard\plain \nowidctlpar \f4\fs20 {\f5
+These controls determine how often data is collected by the service. The sample interval should be as long as possible to minimize the load imposed by the data collection service. Samples can be as frequent as every second, to several days apart. The best
+ interval will depend on the counters being monitored.
+\par }\pard\plain \s2\sb120\nowidctlpar \b\f2 {\f5 Counters
+\par }\pard\plain \nowidctlpar \f4\fs20 {\f5 The counters that are currently selected for logging are displayed in this list box.
+\par }\pard\plain \s2\sb120\nowidctlpar \b\f2 {\f5 Add
+\par }\pard\plain \nowidctlpar \f4\fs20 {\f5
+Select this push button to display the performance counter browsing dialog box. The performance counters to log are selected from this dialog box and then displayed in the Counters list box, when the browser is closed.
+\par }\pard\plain \s2\sb120\nowidctlpar \b\f2 {\f5 Remove
+\par }\pard\plain \nowidctlpar \f4\fs20 {\f5 This push button is used to remove the counters selected in the Counters list box. When this button is selected, all the selected counter entries in the list box will be removed.
+\par }\pard\plain \s1\sb240\nowidctlpar \b\f2\ul {\f5 \page }{\cs15\f5\fs16\up6 #{\footnote \pard\plain \s16\nowidctlpar \f4\fs20 {\cs15\fs16\up6 #} HIDD_OUTPUT_PAGE}}{\f5 Log File
+\par }\pard\plain \nowidctlpar \f4\fs20 {\f5 The Log File property page is used to configure the properties of the log file created by the data collection service.
+\par }\pard\plain \s2\sb120\nowidctlpar \b\f2 {\f5 Log File Format
+\par }\pard\plain \nowidctlpar \f4\fs20 {\f5
+The log file created by the data collection service can be formatted in one of the two ways listed below. Select the one that is appropriate for the application to read or process the data after it has been collected.
+\par }\pard\plain \s3\li360\nowidctlpar \b\f4 {\f5 Comma Separated Variable (.CSV)
+\par }\pard\plain \s17\li720\nowidctlpar \f4\fs20 {\f5 When this format is selected, the data will be written as values separated by a comma.
+\par }\pard\plain \s3\li360\nowidctlpar \b\f4 {\f5 Tab Separated Variable (.TSV)
+\par }\pard\plain \s17\li720\nowidctlpar \f4\fs20 {\f5 When this format is selected, the data will be written as values separated by a tab character.
+\par }\pard\plain \s2\sb120\nowidctlpar \b\f2 {\f5 Manual Filename Assignment
+\par }\pard\plain \nowidctlpar \f4\fs20 {\f5
+Selecting this radio button will cause the data collected by the data collection service to be written to the file specified in the Output Filename edit box. NOTE: That if there is a file with this name already in existence, then the old file will be over
+written by the new file.
+\par }\pard\plain \s3\li360\nowidctlpar \b\f4 {\f5 Output Filename
+\par }\pard\plain \s17\li720\nowidctlpar \f4\fs20 {\f5 This edit box is used to enter the desired output file for the data collection service. The [\'85
+] push button to the right of this edit box can be selected to use the file browser to select the output filename and directory path.
+\par }\pard\plain \s2\sb120\nowidctlpar \b\f2 {\f5 Automatic Filename Assignment
+\par }\pard\plain \nowidctlpar \f4\fs20 {\f5
+Selecting this radio button will cause the output file created by the data collection service to be renamed periodically. The renaming interval as well as the base name and output folder for the files can be configured by the fields in this box as well.
+
+\par }\pard\plain \s3\li360\nowidctlpar \b\f4 {\f5 Rename output file every
+\par }\pard\plain \s17\li720\nowidctlpar \f4\fs20 {\f5 These controls are used to configu
+re the renaming interval of the output files. Enter the number of units directly into the edit box or use the arrows to adjust the number. The units are selected from the combo box next to the digits.
+\par }\pard\plain \s3\li360\nowidctlpar \b\f4 {\f5 Log Folder\'85
+\par }\pard\plain \s17\li720\nowidctlpar \f4\fs20 {\f5
+This push button is used to select the folder that the log files are to be written to. Make sure there is sufficient disk space on the drive containing that folder as the service will terminate if there is no longer enough room to write the data to the o
+utput file.
+\par }\pard\plain \s3\li360\nowidctlpar \b\f4 {\f5 Base Filename
+\par }\pard\plain \s17\li720\nowidctlpar \f4\fs20 {\f5 This edit control
+is used to specify the base file name or the left-most part of the filename. The filename used consists of the base filename followed by a sequence string specified by the Auto Format control. An example of the resulting filename is shown in the Example c
+ontrol at the bottom of this group.
+\par }\pard\plain \s3\li360\nowidctlpar \b\f4 {\f5 Auto Format
+\par }\pard\plain \s17\li720\nowidctlpar \f4\fs20 {\f5 This control is used to specify how the sequence string will be formatted. The letters in the string indicate data will be derived from the following :
+\par }\pard \s17\li1440\nowidctlpar {\b\f5 nnnnnn}{\f5 = a decimal number that increases from 1 to 999,999 by 1 each time a new file is created
+\par }{\b\f5 yy}{\f5 = the last two digits of the current year (1996 = 96)
+\par }{\b\f5 mm}{\f5 = the two digits that describe the current month (Jan = 01)
+\par }{\b\f5 dd}{\f5 = the two digits that describe the current day of the month
+\par }{\b\f5 ddd}{\f5 = the 3 digit day of the current year (i.e. the Julian Date)
+\par }{\b\f5 hh}{\f5 = the 2 digit hour of the day from 0 to 23 ( 5:00 pm = 17)
+\par }\pard\plain \s3\li360\nowidctlpar \b\f4 {\f5 Example
+\par }\pard\plain \s17\li720\nowidctlpar \f4\fs20 {\f5 In this control, an example of what an automatically generated name will look like using the current date and time.
+\par }} \ No newline at end of file
diff --git a/private/sdktools/perflog/pdlcnfig/makefile b/private/sdktools/perflog/pdlcnfig/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/sdktools/perflog/pdlcnfig/makefile.inc b/private/sdktools/perflog/pdlcnfig/makefile.inc
new file mode 100644
index 000000000..fd9adf152
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/makefile.inc
@@ -0,0 +1,10 @@
+pdlcnfig.hlp: hlp\pdlcnfig.hlp
+ copy hlp\pdlcnfig.hlp .
+ binplace pdlcnfig.hlp
+
+pdlcnfig.cnt: hlp\pdlcnfig.cnt
+ copy hlp\pdlcnfig.cnt .
+ binplace pdlcnfig.cnt
+
+
+ \ No newline at end of file
diff --git a/private/sdktools/perflog/pdlcnfig/makehelp.bat b/private/sdktools/perflog/pdlcnfig/makehelp.bat
new file mode 100644
index 000000000..5464da415
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/makehelp.bat
@@ -0,0 +1,26 @@
+@echo off
+REM -- First make map file from Microsoft Visual C++ generated resource.h
+echo // MAKEHELP.BAT generated Help Map file. Used by pdlcnfig.HPJ. >"hlp\pdlcnfig.hm"
+echo. >>"hlp\pdlcnfig.hm"
+echo // Commands (ID_* and IDM_*) >>"hlp\pdlcnfig.hm"
+makehm ID_,HID_,0x10000 IDM_,HIDM_,0x10000 resource.h >>"hlp\pdlcnfig.hm"
+echo. >>"hlp\pdlcnfig.hm"
+echo // Prompts (IDP_*) >>"hlp\pdlcnfig.hm"
+makehm IDP_,HIDP_,0x30000 resource.h >>"hlp\pdlcnfig.hm"
+echo. >>"hlp\pdlcnfig.hm"
+echo // Resources (IDR_*) >>"hlp\pdlcnfig.hm"
+makehm IDR_,HIDR_,0x20000 resource.h >>"hlp\pdlcnfig.hm"
+echo. >>"hlp\pdlcnfig.hm"
+echo // Dialogs (IDD_*) >>"hlp\pdlcnfig.hm"
+makehm IDD_,HIDD_,0x20000 resource.h >>"hlp\pdlcnfig.hm"
+echo. >>"hlp\pdlcnfig.hm"
+echo // Frame Controls (IDW_*) >>"hlp\pdlcnfig.hm"
+makehm IDW_,HIDW_,0x50000 resource.h >>"hlp\pdlcnfig.hm"
+REM -- Make help for Project pdlcnfig
+
+
+echo Building Win32 Help files
+hcrtf -x "hlp\pdlcnfig.hpj"
+
+
+ \ No newline at end of file
diff --git a/private/sdktools/perflog/pdlcnfig/outpage.cpp b/private/sdktools/perflog/pdlcnfig/outpage.cpp
new file mode 100644
index 000000000..d933452fb
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/outpage.cpp
@@ -0,0 +1,926 @@
+// OutPage.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "pdlcnfig.h"
+#include "OutPage.h"
+
+#if _MBCS
+#define _tsplitpath _splitpath
+#else
+#define _tsplitpath _wsplitpath
+#endif
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// COutputPropPage property page
+
+IMPLEMENT_DYNCREATE(COutputPropPage, CPropertyPage)
+
+COutputPropPage::COutputPropPage() : CPropertyPage(COutputPropPage::IDD)
+{
+ //{{AFX_DATA_INIT(COutputPropPage)
+ m_OutputFileName = _T("");
+ m_RenameInterval = 0;
+ m_BaseFileName = _T("");
+ m_AutoNameIndex = -1;
+ m_LogFileTypeIndex = -1;
+ m_RenameUnitsIndex = -1;
+ m_szLogDirectory = _T("");
+ //}}AFX_DATA_INIT
+ m_hKeyLogSettingsDefault = NULL;
+ m_hKeyLogSettings = NULL;
+ m_hKeyLogService = NULL;
+ m_bFileNameChanged = NULL;
+}
+
+COutputPropPage::~COutputPropPage()
+{
+ if (m_hKeyLogSettingsDefault != NULL) RegCloseKey(m_hKeyLogSettingsDefault);
+ if (m_hKeyLogSettings != NULL) RegCloseKey(m_hKeyLogSettings);
+ if (m_hKeyLogService != NULL) RegCloseKey(m_hKeyLogService);
+}
+
+void COutputPropPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(COutputPropPage)
+ DDX_Text(pDX, IDC_OUTPUT_FILE_EDIT, m_OutputFileName);
+ DDV_MaxChars(pDX, m_OutputFileName, 260);
+ DDX_Text(pDX, IDC_RENAME_INTERVAL, m_RenameInterval);
+ DDV_MinMaxDWord(pDX, m_RenameInterval, 0, 99999);
+ DDX_Text(pDX, IDC_BASE_FILENAME_EDIT, m_BaseFileName);
+ DDV_MaxChars(pDX, m_BaseFileName, 260);
+ DDX_CBIndex(pDX, IDC_AUTO_NAME_COMBO, m_AutoNameIndex);
+ DDX_CBIndex(pDX, IDC_LOG_FILETYPE, m_LogFileTypeIndex);
+ DDX_CBIndex(pDX, IDC_RENAME_UNITS, m_RenameUnitsIndex);
+ DDX_Text(pDX, IDC_LOG_DIRECTORY, m_szLogDirectory);
+ DDV_MaxChars(pDX, m_szLogDirectory, 260);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(COutputPropPage, CPropertyPage)
+ //{{AFX_MSG_MAP(COutputPropPage)
+ ON_BN_CLICKED(IDC_AUTOMATIC_NAME, OnAutomaticName)
+ ON_BN_CLICKED(IDC_MANUAL_NAME, OnManualName)
+ ON_CBN_SELCHANGE(IDC_AUTO_NAME_COMBO, OnSelchangeAutoNameCombo)
+ ON_EN_CHANGE(IDC_BASE_FILENAME_EDIT, OnChangeBaseFilenameEdit)
+ ON_BN_CLICKED(IDC_BROWSE_OUTPUT_FILE, OnBrowseOutputFile)
+ ON_CBN_SELCHANGE(IDC_LOG_FILETYPE, OnSelchangeLogFiletype)
+ ON_CBN_SELCHANGE(IDC_RENAME_UNITS, OnSelchangeRenameUnits)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_RENAME_INTERVAL, OnDeltaposSpinRenameInterval)
+ ON_EN_CHANGE(IDC_OUTPUT_FILE_EDIT, OnChangeOutputFileEdit)
+ ON_EN_CHANGE(IDC_RENAME_INTERVAL, OnChangeRenameInterval)
+ ON_EN_UPDATE(IDC_BASE_FILENAME_EDIT, OnUpdateBaseFilenameEdit)
+ ON_BN_CLICKED(IDC_BROWSE_FOLDER, OnBrowseFolder)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+void COutputPropPage::AutoManualEnable (BOOL bAutomatic)
+{
+ GetDlgItem(IDC_MANUAL_NAME_GROUP)->EnableWindow(!bAutomatic);
+ GetDlgItem(IDC_OUTPUT_FILE_EDIT)->EnableWindow(!bAutomatic);
+ GetDlgItem(IDC_BROWSE_OUTPUT_FILE)->EnableWindow(!bAutomatic);
+
+ GetDlgItem(IDC_AUTO_NAME_GROUP)->EnableWindow(bAutomatic);
+ GetDlgItem(IDC_RENAME_INTERVAL_CAPTION)->EnableWindow(bAutomatic);
+ GetDlgItem(IDC_RENAME_INTERVAL)->EnableWindow(bAutomatic);
+ GetDlgItem(IDC_SPIN_RENAME_INTERVAL)->EnableWindow(bAutomatic);
+ GetDlgItem(IDC_RENAME_UNITS)->EnableWindow(bAutomatic);
+ GetDlgItem(IDC_BROWSE_FOLDER)->EnableWindow(bAutomatic);
+ GetDlgItem(IDC_LOG_DIRECTORY)->EnableWindow(bAutomatic);
+ GetDlgItem(IDC_BASE_NAME_CAPTION)->EnableWindow(bAutomatic);
+ GetDlgItem(IDC_BASE_FILENAME_EDIT)->EnableWindow(bAutomatic);
+ GetDlgItem(IDC_AUTO_NAME_CAPTION)->EnableWindow(bAutomatic);
+ GetDlgItem(IDC_AUTO_NAME_COMBO)->EnableWindow(bAutomatic);
+ GetDlgItem(IDC_SAMPLE_NAME)->EnableWindow(bAutomatic);
+ GetDlgItem(IDC_SAMPLE_NAME_TEXT)->EnableWindow(bAutomatic);
+}
+
+void COutputPropPage::UpdateSampleFilename()
+{
+ CString cCompositeName;
+ CString cBaseName;
+ CString cDateString;
+ CString cFileTypeString;
+ CTime cCurrentTime = CTime::GetCurrentTime();
+ LONG lAutoNameFormat;
+ LONG lFileTypeIndex;
+
+ if (IsDlgButtonChecked (IDC_AUTOMATIC_NAME)) {
+ // only update if the automatic button is checked
+ // get base name text
+ GetDlgItemText (IDC_BASE_FILENAME_EDIT, cBaseName);
+ cBaseName += TEXT("_");
+
+ // get date/time/serial integer format
+ cCurrentTime.GetCurrentTime();
+ lAutoNameFormat = ((CComboBox *)GetDlgItem(IDC_AUTO_NAME_COMBO))->GetCurSel();
+ switch (lAutoNameFormat) {
+ case OPD_NAME_NNNNNN:
+ cDateString = TEXT("000001");
+ break;
+
+ case OPD_NAME_YYDDD:
+ cDateString = cCurrentTime.Format (TEXT("%y%j"));
+ break;
+
+ case OPD_NAME_YYMM:
+ cDateString = cCurrentTime.Format (TEXT("%y%m"));
+ break;
+
+ case OPD_NAME_YYMMDDHH:
+ cDateString = cCurrentTime.Format (TEXT("%y%m%d%H"));
+ break;
+
+ case OPD_NAME_MMDDHH:
+ cDateString = cCurrentTime.Format (TEXT("%m%d%H"));
+ break;
+
+ case OPD_NAME_YYMMDD:
+ default:
+ cDateString = cCurrentTime.Format (TEXT("%y%m%d"));
+ break;
+ }
+
+ // get file type
+ lFileTypeIndex = ((CComboBox *)GetDlgItem(IDC_LOG_FILETYPE))->GetCurSel();
+ switch (lFileTypeIndex) {
+ case OPD_TSV_FILE:
+ cFileTypeString = TEXT(".TSV");
+ break;
+
+#if 0
+ case OPD_BIN_FILE:
+ cFileTypeString = TEXT(".BLG");
+ break;
+#endif
+ case OPD_CSV_FILE:
+ default:
+ cFileTypeString = TEXT(".CSV");
+ break;
+ }
+ cCompositeName = cBaseName;
+ cCompositeName += cDateString;
+ cCompositeName += cFileTypeString;
+
+ SetDlgItemText (IDC_SAMPLE_NAME_TEXT, cCompositeName);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// COutputPropPage message handlers
+
+BOOL COutputPropPage::OnInitDialog()
+{
+ LONG lStatus;
+
+ DWORD dwRegValType;
+ DWORD dwRegValue;
+ DWORD dwRegValueSize;
+
+ CString csTempFilePath;
+
+ TCHAR szRegString[MAX_PATH];
+ TCHAR szDriveName[MAX_PATH];
+
+ BOOL bAutoMode = FALSE;
+
+ // open registry key to service
+ lStatus = RegOpenKeyEx (
+ HKEY_LOCAL_MACHINE,
+ TEXT("SYSTEM\\CurrentControlSet\\Services\\PerfDataLog"),
+ 0,
+ KEY_READ | KEY_WRITE,
+ &m_hKeyLogService);
+
+ // open registry to log query info
+ lStatus = RegOpenKeyEx (
+ m_hKeyLogService,
+ TEXT("Log Queries"),
+ 0,
+ KEY_READ | KEY_WRITE,
+ &m_hKeyLogSettings);
+
+ // open registry to default log query
+ lStatus = RegOpenKeyEx (
+ m_hKeyLogSettings,
+ TEXT("Default"),
+ 0,
+ KEY_READ | KEY_WRITE,
+ &m_hKeyLogSettingsDefault);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // display error, close dialog and exit
+ }
+ // continue
+
+ // read log file format
+ dwRegValType = 0;
+ dwRegValue = 0;
+ dwRegValueSize = sizeof(DWORD);
+ lStatus = RegQueryValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Log File Type"),
+ NULL,
+ &dwRegValType,
+ (LPBYTE)&dwRegValue,
+ &dwRegValueSize);
+ if (lStatus != ERROR_SUCCESS) {
+ // then apply default value
+ dwRegValue = OPD_CSV_FILE;
+ }
+
+ m_LogFileTypeIndex = dwRegValue;
+
+ // set default mode
+ dwRegValType = 0;
+ dwRegValue = 0;
+ dwRegValueSize = sizeof(DWORD);
+ lStatus = RegQueryValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Auto Name Interval"),
+ NULL,
+ &dwRegValType,
+ (LPBYTE)&dwRegValue,
+ &dwRegValueSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // then apply default value
+ dwRegValue = 0; // manual naming is the default
+ } else if (dwRegValType != REG_DWORD) {
+ // then apply default value
+ dwRegValue = 0; // manual naming is the default
+ } // else assume it was OK
+
+ if (dwRegValue == 0) {
+ // then manual naming has been selected:
+ CheckRadioButton (IDC_MANUAL_NAME, IDC_AUTOMATIC_NAME, IDC_MANUAL_NAME);
+ // initialize the rest of the field(s)
+ dwRegValType = 0;
+ dwRegValueSize = MAX_PATH * sizeof(TCHAR);
+ memset (szRegString, 0, dwRegValueSize);
+ lStatus = RegQueryValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Log Filename"),
+ NULL,
+ &dwRegValType,
+ (LPBYTE)&szRegString[0],
+ &dwRegValueSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // apply default name
+ lstrcpy (szRegString, TEXT("perfdata."));
+ switch (m_LogFileTypeIndex) {
+ case OPD_TSV_FILE:
+ lstrcat (szRegString, TEXT("tsv"));
+ break;
+
+ case OPD_BIN_FILE:
+ lstrcat (szRegString, TEXT("blg"));
+ break;
+
+ case (OPD_CSV_FILE):
+ default:
+ lstrcat (szRegString, TEXT("csv"));
+ break;
+ }
+ }
+ // if the filename doesn't specify a directory, then use the
+ csTempFilePath = szRegString;
+
+ _tsplitpath ((LPCTSTR)csTempFilePath, szDriveName, szRegString,
+ NULL, NULL);
+ if ((lstrlen(szDriveName) == 0) && (lstrlen(szRegString) == 0)) {
+ // default log file directory
+ dwRegValType = 0;
+ dwRegValueSize = MAX_PATH * sizeof(TCHAR);
+ memset (szRegString, 0, dwRegValueSize);
+ lStatus = RegQueryValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Log Default Directory"),
+ NULL,
+ &dwRegValType,
+ (LPBYTE)&szRegString[0],
+ &dwRegValueSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // try to use the general default
+ dwRegValType = 0;
+ dwRegValueSize = MAX_PATH * sizeof(TCHAR);
+ memset (szRegString, 0, dwRegValueSize);
+ lStatus = RegQueryValueEx (
+ m_hKeyLogSettings,
+ TEXT("Log Default Directory"),
+ NULL,
+ &dwRegValType,
+ (LPBYTE)&szRegString[0],
+ &dwRegValueSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // apply the default then since we can't find it
+ // in the registry anywhere
+ lstrcpy (szRegString, TEXT("c:\\perflogs"));
+ }
+ }
+ // szRegString should have a valid path here
+ m_szLogDirectory = szRegString; // load default dir for auto section
+ m_OutputFileName = szRegString;
+ m_OutputFileName += TEXT ("\\");
+ } else {
+ m_szLogDirectory = szDriveName;
+ // the file parsing function leaves the trailing backslash
+ // so remove it before concatenating it.
+ if (szRegString[lstrlen(szRegString)-1] == TEXT('\\')) {
+ szRegString[lstrlen(szRegString)-1] = 0;
+ }
+ m_szLogDirectory += szRegString;
+ m_OutputFileName.Empty();
+ }
+ m_OutputFileName += csTempFilePath;
+
+ // set auto combo boxes to default values
+
+ m_BaseFileName = TEXT("perfdata");
+ m_AutoNameIndex = OPD_NAME_YYMMDD;
+ m_RenameUnitsIndex = OPD_RENAME_DAYS;
+ m_RenameInterval = 1;
+
+ bAutoMode = FALSE;
+ } else {
+ CheckRadioButton (IDC_MANUAL_NAME, IDC_AUTOMATIC_NAME, IDC_AUTOMATIC_NAME);
+ m_RenameInterval = dwRegValue;
+ // get values for controls
+ dwRegValType = 0;
+ dwRegValueSize = MAX_PATH * sizeof(TCHAR);
+ memset (szRegString, 0, dwRegValueSize);
+ lStatus = RegQueryValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Log Default Directory"),
+ NULL,
+ &dwRegValType,
+ (LPBYTE)&szRegString[0],
+ &dwRegValueSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // try to use the general default
+ dwRegValType = 0;
+ dwRegValueSize = MAX_PATH * sizeof(TCHAR);
+ memset (szRegString, 0, dwRegValueSize);
+ lStatus = RegQueryValueEx (
+ m_hKeyLogSettings,
+ TEXT("Log Default Directory"),
+ NULL,
+ &dwRegValType,
+ (LPBYTE)&szRegString[0],
+ &dwRegValueSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // apply the default then since we can't find it
+ // in the registry anywhere
+ lstrcpy (szRegString, TEXT("c:\\perflogs"));
+ }
+ }
+ // szRegString should have a valid path here
+ m_szLogDirectory = szRegString;
+
+ // base filename
+ dwRegValType = 0;
+ dwRegValueSize = MAX_PATH * sizeof(TCHAR);
+ memset (szRegString, 0, dwRegValueSize);
+ lStatus = RegQueryValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Base Filename"),
+ NULL,
+ &dwRegValType,
+ (LPBYTE)&szRegString[0],
+ &dwRegValueSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // apply default name
+ lstrcpy (szRegString, TEXT("perfdata"));
+ }
+ m_BaseFileName = szRegString;
+
+ // get auto name format
+ dwRegValType = 0;
+ dwRegValue = 0;
+ dwRegValueSize = sizeof(DWORD);
+ lStatus = RegQueryValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Log File Auto Format"),
+ NULL,
+ &dwRegValType,
+ (LPBYTE)&dwRegValue,
+ &dwRegValueSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // then apply default value
+ dwRegValue = OPD_NAME_YYMMDD; // manual naming is the default
+ }
+ // set update interval information
+ m_AutoNameIndex = dwRegValue;
+
+ dwRegValType = 0;
+ dwRegValue = 0;
+ dwRegValueSize = sizeof(DWORD);
+ lStatus = RegQueryValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Auto Rename Units"),
+ NULL,
+ &dwRegValType,
+ (LPBYTE)&dwRegValue,
+ &dwRegValueSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // then apply default value
+ dwRegValue = OPD_RENAME_DAYS; // manual naming is the default
+ }
+ m_RenameUnitsIndex = dwRegValue;
+
+ bAutoMode = TRUE;
+ }
+
+ CPropertyPage::OnInitDialog();
+
+ // now finish updating the controls in the property page
+ UpdateSampleFilename();
+
+ // update control state to match selection
+ AutoManualEnable (bAutoMode);
+
+ SetModified(FALSE);
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void COutputPropPage::OnAutomaticName()
+{
+ AutoManualEnable(TRUE);
+ UpdateSampleFilename();
+ SetModified(TRUE);
+}
+
+void COutputPropPage::OnManualName()
+{
+ AutoManualEnable(FALSE);
+ SetModified(TRUE);
+}
+
+void COutputPropPage::OnSelchangeAutoNameCombo()
+{
+ // TODO: Add your control notification handler code here
+ UpdateSampleFilename();
+ m_bFileNameChanged = TRUE;
+ SetModified(TRUE);
+}
+
+void COutputPropPage::OnChangeBaseFilenameEdit()
+{
+ // TODO: Add your control notification handler code here
+ SetModified(TRUE);
+ m_bFileNameChanged = TRUE;
+}
+
+void COutputPropPage::OnBrowseOutputFile()
+{
+ OPENFILENAME ofn;
+ CComboBox *cFileTypeCombo;
+ CString csInitialDir;
+ LONG lLogFileType;
+ TCHAR szFileName[MAX_PATH];
+ CString csBaseFilename;
+ TCHAR szDrive[MAX_PATH];
+ TCHAR szDir[MAX_PATH];
+ TCHAR szExt[MAX_PATH];
+ LPTSTR szDefExt = NULL;
+
+ cFileTypeCombo = (CComboBox *)GetDlgItem(IDC_LOG_FILETYPE);
+ lLogFileType = cFileTypeCombo->GetCurSel();
+ if (lLogFileType == CB_ERR) lLogFileType = OPD_NUM_FILE_TYPES;
+
+ GetDlgItemText (IDC_OUTPUT_FILE_EDIT, csBaseFilename);
+ _tsplitpath((LPCTSTR)csBaseFilename,
+ szDrive, szDir, szFileName, szExt);
+
+ csInitialDir = szDrive;
+ csInitialDir += szDir;
+
+ lstrcat (szFileName, szExt);
+
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = m_hWnd;
+ ofn.hInstance = GetModuleHandle(NULL);
+ ofn.lpstrFilter = TEXT("CSV Files (*.csv)\0*.csv\0TSV Files (*.tsv)\0*.tsv\0BLG Files (*.blg)\0*.blg\0All Files (*.*)\0*.*\0");
+ ofn.lpstrCustomFilter = NULL;
+ ofn.nMaxCustFilter = 0;
+ ofn.nFilterIndex = lLogFileType + 1; // nFilterIndex is 1-based
+ ofn.lpstrFile = szFileName;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = (LPCTSTR)csInitialDir;
+ ofn.lpstrTitle = TEXT("Select Log Filename");
+ ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
+ ofn.nFileOffset = 0;
+ ofn.nFileExtension = 0;
+ ofn.lpstrDefExt = NULL;
+ ofn.lCustData = 0;
+ ofn.lpfnHook = NULL;
+ ofn.lpTemplateName = NULL;
+
+ if (GetOpenFileName (&ofn) == IDOK) {
+ // Update the fields with the new information
+ cFileTypeCombo->SetCurSel(ofn.nFilterIndex-1);
+ // see if an file name extension needs to be added...
+ if (ofn.nFileExtension == 0) {
+ // then add the one that matches the current file type
+ switch (ofn.nFilterIndex-1) {
+ case OPD_CSV_FILE:
+ szDefExt = TEXT(".csv");
+ break;
+
+ case OPD_TSV_FILE:
+ szDefExt = TEXT(".tsv");
+ break;
+
+ case OPD_BIN_FILE:
+ szDefExt = TEXT(".blg");
+ break;
+
+ default:
+ szDefExt = NULL;
+ break;
+ }
+ }
+ if (szDefExt != NULL) {
+ lstrcat (szFileName, szDefExt);
+ }
+
+ SetDlgItemText (IDC_OUTPUT_FILE_EDIT, szFileName);
+ } // else ignore if they canceled out
+}
+
+void COutputPropPage::OnSelchangeLogFiletype()
+{
+ // TODO: Add your control notification handler code here
+ UpdateSampleFilename();
+ m_bFileNameChanged = TRUE;
+ SetModified(TRUE);
+}
+
+void COutputPropPage::OnSelchangeRenameUnits()
+{
+ LONG lIndex;
+ LONG lNewDefault;
+ // Get new sample and update default extension based on rename
+ // interval units
+ lIndex = ((CComboBox *)GetDlgItem(IDC_RENAME_UNITS))->GetCurSel();
+ switch (lIndex) {
+ case OPD_RENAME_HOURS:
+ lNewDefault = OPD_NAME_YYMMDDHH;
+ break;
+
+ case OPD_RENAME_DAYS:
+ lNewDefault = OPD_NAME_YYMMDD;
+ break;
+
+ case OPD_RENAME_MONTHS:
+ lNewDefault = OPD_NAME_YYMM;
+ break;
+
+ case OPD_RENAME_KBYTES:
+ case OPD_RENAME_MBYTES:
+ default:
+ lNewDefault = OPD_NAME_NNNNNN;
+ break;
+ }
+ // update new default selection
+ ((CComboBox *)GetDlgItem(IDC_AUTO_NAME_COMBO))->SetCurSel(lNewDefault);
+
+ UpdateSampleFilename();
+ SetModified(TRUE);
+}
+
+void COutputPropPage::OnDeltaposSpinRenameInterval(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ TCHAR szStringValue[MAX_PATH];
+ DWORD dwNumValue;
+ int nChange;
+
+ NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
+
+ // get current value from edit window
+ GetDlgItemText (IDC_RENAME_INTERVAL, szStringValue, MAX_PATH);
+
+ // convert to integer
+ dwNumValue = _tcstoul (szStringValue, NULL, 10);
+ // delta is opposite of arrow direction
+ nChange = -pNMUpDown->iDelta;
+
+ // apply value from spin control
+ if (nChange < 0) { // 1 is the minimum
+ // make sure we haven't hit bottom already
+ if (dwNumValue > 1) {
+ dwNumValue += nChange;
+ }
+ } else {
+ dwNumValue += nChange;
+ }
+
+ // update edit window
+ _ultot (dwNumValue, szStringValue, 10);
+
+ SetDlgItemText(IDC_RENAME_INTERVAL, szStringValue);
+
+ SetModified(TRUE);
+
+ *pResult = 0;
+}
+
+void COutputPropPage::OnCancel()
+{
+ // TODO: Add your specialized code here and/or call the base class
+
+ CPropertyPage::OnCancel();
+}
+
+void COutputPropPage::OnOK()
+{
+ LONG lIndex;
+ LONG lStatus;
+ CString csFilename;
+
+ DWORD dwAutoNameFormat;
+ DWORD dwAutoChangeInterval;
+ BOOL bManual;
+ BOOL bBogus = FALSE;
+
+ bManual = IsDlgButtonChecked (IDC_MANUAL_NAME);
+ if (!bManual) {
+ dwAutoNameFormat = ((CComboBox *)GetDlgItem(IDC_AUTO_NAME_COMBO))->GetCurSel();
+ dwAutoChangeInterval = ((CComboBox *)GetDlgItem(IDC_RENAME_UNITS))->GetCurSel();
+ // check for valid interval/name combinations
+ switch (dwAutoChangeInterval) {
+ case OPD_RENAME_HOURS:
+ if ((dwAutoNameFormat == OPD_NAME_YYDDD) ||
+ (dwAutoNameFormat == OPD_NAME_YYMM) ||
+ (dwAutoNameFormat == OPD_NAME_YYMMDD)) bBogus = TRUE;
+ break;
+
+ case OPD_RENAME_DAYS:
+ if (dwAutoNameFormat == OPD_NAME_YYMM) bBogus = TRUE;
+ break;
+
+ case OPD_RENAME_MONTHS:
+ break;
+
+ case OPD_RENAME_KBYTES:
+ case OPD_RENAME_MBYTES:
+ default:
+ if (dwAutoNameFormat != OPD_NAME_NNNNNN) bBogus = TRUE;
+ break;
+ }
+ }
+
+ if (bBogus) {
+ // display warning
+ if (AfxMessageBox (IDS_NAME_FORMAT_NOT_COMPATIBLE,
+ IDS_WARNING, MB_OKCANCEL) == IDCANCEL) {
+ SetModified(TRUE);
+ return;
+ }
+ }
+ // save Log File Type
+ lIndex = ((CComboBox *)GetDlgItem(IDC_LOG_FILETYPE))->GetCurSel();
+
+ lStatus = RegSetValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Log File Type"),
+ 0L,
+ REG_DWORD,
+ (LPBYTE)&lIndex,
+ sizeof(lIndex));
+
+ ASSERT (lStatus == ERROR_SUCCESS);
+
+ // is manual filename button pushed?
+ if (bManual) {
+ // YES:
+ csFilename.Empty();
+ // write output filename frome edit box
+ GetDlgItemText(IDC_OUTPUT_FILE_EDIT, csFilename);
+
+ lStatus = RegSetValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Log Filename"),
+ 0L,
+ REG_SZ,
+ (LPBYTE)(LPCTSTR)csFilename,
+ (csFilename.GetLength()+1)*sizeof(TCHAR));
+
+ ASSERT (lStatus == ERROR_SUCCESS);
+
+ // write rename interval == 0
+ lIndex = 0;
+ lStatus = RegSetValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Auto Name Interval"),
+ 0L,
+ REG_DWORD,
+ (LPBYTE)&lIndex,
+ sizeof(lIndex));
+
+ ASSERT (lStatus == ERROR_SUCCESS);
+
+ // clear auto rename entries:
+ // Log File Auto Format
+ RegDeleteValue (m_hKeyLogSettingsDefault, TEXT("Log File Auto Format"));
+ // Log Auto Name Units
+ RegDeleteValue (m_hKeyLogSettingsDefault, TEXT("Auto Rename Units"));
+ // Log Base Filename
+ RegDeleteValue (m_hKeyLogSettingsDefault, TEXT("Base Log Filename"));
+ } else {
+ // auto is pressed so:
+ csFilename.Empty();
+ // save Log Default Directory
+ GetDlgItemText (IDC_LOG_DIRECTORY, csFilename);
+ lStatus = RegSetValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Log Default Directory"),
+ 0L,
+ REG_SZ,
+ (LPBYTE)(LPCTSTR)csFilename,
+ (csFilename.GetLength()+1)*sizeof(TCHAR));
+
+ ASSERT (lStatus == ERROR_SUCCESS);
+
+ // save Log Base Filename
+ csFilename.Empty();
+ GetDlgItemText (IDC_BASE_FILENAME_EDIT, csFilename);
+ lStatus = RegSetValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Base Filename"),
+ 0L,
+ REG_SZ,
+ (LPBYTE)(LPCTSTR)csFilename,
+ (csFilename.GetLength()+1)*sizeof(TCHAR));
+
+ ASSERT (lStatus == ERROR_SUCCESS);
+
+ // save Log Auto Name Format
+ lStatus = RegSetValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Log File Auto Format"),
+ 0L,
+ REG_DWORD,
+ (LPBYTE)&dwAutoNameFormat,
+ sizeof(DWORD));
+
+ ASSERT (lStatus == ERROR_SUCCESS);
+
+ if (lIndex == OPD_NAME_NNNNNN) {
+ if (m_bFileNameChanged) {
+ // reset serial number counter to 1
+ lIndex = 1;
+ lStatus = RegSetValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Log File Serial Number"),
+ 0L,
+ REG_DWORD,
+ (LPBYTE)&lIndex,
+ sizeof(DWORD));
+ ASSERT (lStatus == ERROR_SUCCESS);
+ }
+ } else {
+ // delete serial number entry
+ lStatus = RegDeleteValue (
+ m_hKeyLogSettingsDefault,
+ TEXT("Log File Serial Number"));
+ // this may fail if the key is already
+ // deleted. That's ok.
+ }
+ // save Log Rename Interval
+ csFilename.Empty();
+ GetDlgItemText (IDC_RENAME_INTERVAL, csFilename);
+ lIndex = _tcstol((LPCTSTR)csFilename, NULL, 10);
+ lStatus = RegSetValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Auto Name Interval"),
+ 0L,
+ REG_DWORD,
+ (LPBYTE)&lIndex,
+ sizeof(DWORD));
+
+ ASSERT (lStatus == ERROR_SUCCESS);
+
+ // save Log Rename Units
+ lStatus = RegSetValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Auto Rename Units"),
+ 0L,
+ REG_DWORD,
+ (LPBYTE)&dwAutoChangeInterval,
+ sizeof(DWORD));
+
+ ASSERT (lStatus == ERROR_SUCCESS);
+
+ // clear Manual entries
+ // Log Filename
+ RegDeleteValue (m_hKeyLogSettingsDefault, TEXT("Log Filename"));
+ }
+ CancelToClose();
+}
+
+BOOL COutputPropPage::OnQueryCancel()
+{
+ // TODO: Add your specialized code here and/or call the base class
+
+ return CPropertyPage::OnQueryCancel();
+}
+
+void COutputPropPage::OnChangeOutputFileEdit()
+{
+ // TODO: Add your control notification handler code here
+ SetModified(TRUE);
+}
+
+void COutputPropPage::OnChangeRenameInterval()
+{
+ // TODO: Add your control notification handler code here
+ SetModified(TRUE);
+}
+
+void COutputPropPage::OnUpdateBaseFilenameEdit()
+{
+ // TODO: Add your control notification handler code here
+ UpdateSampleFilename();
+ m_bFileNameChanged = TRUE;
+}
+
+void COutputPropPage::OnBrowseFolder()
+{
+ OPENFILENAME ofn;
+ CComboBox *cFileTypeCombo;
+ CString csInitialDir;
+ LONG lLogFileType;
+ TCHAR szFileName[MAX_PATH];
+ CString csBaseFilename;
+ LONG lFileNameLength;
+
+ cFileTypeCombo = (CComboBox *)GetDlgItem(IDC_LOG_FILETYPE);
+ lLogFileType = cFileTypeCombo->GetCurSel();
+ if (lLogFileType == CB_ERR) lLogFileType = OPD_NUM_FILE_TYPES;
+
+ // should the default filename be the base or the synthesized one?
+ GetDlgItemText (IDC_BASE_FILENAME_EDIT, szFileName, MAX_PATH);
+ GetDlgItemText (IDC_LOG_DIRECTORY, csInitialDir);
+
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = m_hWnd;
+ ofn.hInstance = GetModuleHandle(NULL);
+ ofn.lpstrFilter = TEXT("CSV Files (*.csv)\0*.csv\0TSV Files (*.tsv)\0*.tsv\0BLG Files (*.blg)\0*.blg\0All Files (*.*)\0*.*\0");
+ ofn.lpstrCustomFilter = NULL;
+ ofn.nMaxCustFilter = 0;
+ ofn.nFilterIndex = lLogFileType + 1; // nFilterIndex is 1 based
+ ofn.lpstrFile = szFileName;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = csInitialDir;
+ ofn.lpstrTitle = TEXT("Select Log Folder and Base Filename");
+ ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
+ ofn.nFileOffset = 0;
+ ofn.nFileExtension = 0;
+ ofn.lpstrDefExt = NULL;
+ ofn.lCustData = 0;
+ ofn.lpfnHook = NULL;
+ ofn.lpTemplateName = NULL;
+
+ if (GetOpenFileName (&ofn) == IDOK) {
+ // Update the fields with the new information
+ cFileTypeCombo->SetCurSel(ofn.nFilterIndex -1);
+
+ lFileNameLength = lstrlen(szFileName);
+ // truncate extension
+ if ((ofn.nFileExtension < lFileNameLength) && (ofn.nFileExtension > 0)) {
+ szFileName[ofn.nFileExtension-1] = 0;
+ }
+ if ((ofn.nFileOffset < lFileNameLength) && (ofn.nFileOffset >= 0)){
+ csBaseFilename = &szFileName[ofn.nFileOffset];
+ if (ofn.nFileOffset > 0) {
+ szFileName[ofn.nFileOffset-1] = 0;
+ }
+ SetDlgItemText (IDC_BASE_FILENAME_EDIT, csBaseFilename);
+ SetDlgItemText (IDC_LOG_DIRECTORY, szFileName);
+ }
+ UpdateSampleFilename();
+ } // else ignore if they canceled out
+}
+
diff --git a/private/sdktools/perflog/pdlcnfig/outpage.h b/private/sdktools/perflog/pdlcnfig/outpage.h
new file mode 100644
index 000000000..4598d1682
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/outpage.h
@@ -0,0 +1,68 @@
+// OutPage.h : header file
+//
+#include "common.h"
+/////////////////////////////////////////////////////////////////////////////
+// COutputPropPage dialog
+
+class COutputPropPage : public CPropertyPage
+{
+ DECLARE_DYNCREATE(COutputPropPage)
+
+// Construction
+public:
+ COutputPropPage();
+ ~COutputPropPage();
+
+// Dialog Data
+ //{{AFX_DATA(COutputPropPage)
+ enum { IDD = IDD_OUTPUT_PAGE };
+ CString m_OutputFileName;
+ DWORD m_RenameInterval;
+ CString m_BaseFileName;
+ int m_AutoNameIndex;
+ int m_LogFileTypeIndex;
+ int m_RenameUnitsIndex;
+ CString m_szLogDirectory;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generate virtual function overrides
+ //{{AFX_VIRTUAL(COutputPropPage)
+ public:
+ virtual void OnCancel();
+ virtual void OnOK();
+ virtual BOOL OnQueryCancel();
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(COutputPropPage)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnAutomaticName();
+ afx_msg void OnManualName();
+ afx_msg void OnSelchangeAutoNameCombo();
+ afx_msg void OnChangeBaseFilenameEdit();
+ afx_msg void OnBrowseOutputFile();
+ afx_msg void OnSelchangeLogFiletype();
+ afx_msg void OnSelchangeRenameUnits();
+ afx_msg void OnDeltaposSpinRenameInterval(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnChangeOutputFileEdit();
+ afx_msg void OnChangeRenameInterval();
+ afx_msg void OnUpdateBaseFilenameEdit();
+ afx_msg void OnBrowseFolder();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+ void AutoManualEnable (BOOL bAutomatic);
+ void UpdateSampleFilename();
+
+ HKEY m_hKeyLogSettingsDefault;
+ HKEY m_hKeyLogSettings;
+ HKEY m_hKeyLogService;
+ BOOL m_bFileNameChanged;
+};
+
diff --git a/private/sdktools/perflog/pdlcnfig/pdlcnfig.cpp b/private/sdktools/perflog/pdlcnfig/pdlcnfig.cpp
new file mode 100644
index 000000000..690bcc830
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/pdlcnfig.cpp
@@ -0,0 +1,360 @@
+// pdlcnfig.cpp : Defines the class behaviors for the application.
+//
+
+#include "stdafx.h"
+#include "pdlcnfig.h"
+#include "OutPage.h"
+#include "SetPage.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CPdlConfigApp
+
+BEGIN_MESSAGE_MAP(CPdlConfigApp, CWinApp)
+ //{{AFX_MSG_MAP(CPdlConfigApp)
+ // NOTE - the ClassWizard will add and remove mapping macros here.
+ // DO NOT EDIT what you see in these blocks of generated code!
+ //}}AFX_MSG
+ ON_COMMAND(ID_HELP, CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CPdlConfigApp construction
+
+CPdlConfigApp::CPdlConfigApp()
+{
+ // TODO: add construction code here,
+ // Place all significant initialization in InitInstance
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only CPdlConfigApp object
+
+CPdlConfigApp theApp;
+
+/////////////////////////////////////////////////////////////////////////////
+// Test for installation of the service.
+
+LONG CPdlConfigApp::PerfLogServiceStatus()
+{
+ HKEY hKeyLogService;
+ LONG lStatus;
+
+ // try opening the key to the service
+ lStatus = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
+ TEXT("SYSTEM\\CurrentControlSet\\Services\\PerfDataLog"),
+ 0,
+ KEY_READ | KEY_WRITE,
+ &hKeyLogService);
+
+ if (lStatus == ERROR_SUCCESS) {
+ // don't keep the key open
+ RegCloseKey (hKeyLogService);
+ }
+
+ return lStatus;
+}
+
+LONG CPdlConfigApp::ServiceFilesCopied()
+{
+ HANDLE hFile = INVALID_HANDLE_VALUE;
+ LONG lStatus = ERROR_SUCCESS;
+ TCHAR szFullPathName[MAX_PATH];
+
+ ExpandEnvironmentStrings (
+ TEXT("%windir%\\system32\\pdlsvc.exe"),
+ szFullPathName, MAX_PATH);
+
+ hFile = CreateFile (
+ szFullPathName,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ lStatus = GetLastError();
+ } else {
+ CloseHandle (hFile);
+ lStatus = ERROR_SUCCESS;
+ }
+
+ return lStatus;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CPdlConfigApp initialization
+
+LONG CPdlConfigApp::CreatePerfDataLogService ()
+{
+ LONG lStatus = ERROR_SUCCESS;
+ HKEY hKeyServices = NULL;
+ HKEY hKeyPerfLog = NULL;
+ HKEY hKeyPerfAlert = NULL;
+ DWORD dwWaitLimit = 20;
+ SC_HANDLE hSC;
+ SC_HANDLE hLogService;
+ SC_HANDLE hAlertService;
+
+ // create service
+
+ hSC = OpenSCManager (NULL, NULL, SC_MANAGER_CREATE_SERVICE);
+
+ if (hSC == NULL) {
+ // display error message
+ lStatus = GetLastError();
+ }
+
+ if (lStatus == ERROR_SUCCESS) {
+ hLogService = CreateService (hSC,
+ TEXT("PerfDataLog"),
+ TEXT("Performance Data Log"),
+ SERVICE_ALL_ACCESS,
+ SERVICE_WIN32_OWN_PROCESS,
+ SERVICE_DEMAND_START,
+ SERVICE_ERROR_NORMAL,
+ TEXT("%systemroot%\\system32\\pdlsvc.exe"),
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+
+ if (hLogService == NULL) {
+ lStatus = GetLastError();
+ } else {
+ lStatus = ERROR_SUCCESS;
+ CloseServiceHandle (hLogService);
+ }
+
+ if (lStatus == ERROR_SUCCESS) {
+ // wait until the registry is updated before continuing
+ while (lStatus = RegOpenKeyEx (
+ HKEY_LOCAL_MACHINE,
+ TEXT("System\\CurrentControlSet\\Services\\PerfDataLog"),
+ 0,
+ KEY_READ | KEY_WRITE,
+ &hKeyPerfLog) != ERROR_SUCCESS) {
+ Sleep (500); // wait .5 seconds and try again
+ if (--dwWaitLimit == 0) {
+ AfxMessageBox (IDS_SC_CREATE_ERROR);
+ break;
+ }
+ }
+
+ if (lStatus == ERROR_SUCCESS) {
+ RegCloseKey (hKeyPerfLog);
+ }
+ }
+
+ CloseServiceHandle (hSC);
+ }
+
+ return lStatus;
+}
+
+LONG CPdlConfigApp::InitPerfDataLogRegistry ()
+{
+ LONG lStatus = ERROR_SUCCESS;
+
+ HKEY hKeyPerfLog = NULL;
+ HKEY hKeyLogQueries = NULL;
+ HKEY hKeyLogQueriesDefault = NULL;
+
+ HKEY hKeyPerfAlert = NULL;
+ HKEY hKeyAlertQueries = NULL;
+ HKEY hKeyAlertQueriesDefault = NULL;
+
+ HKEY hKeyEventLogApplication = NULL;
+ HKEY hKeyEventLogPerfDataLog = NULL;
+ HKEY hKeyEventLogPerfDataAlert = NULL;
+
+ DWORD dwValue;
+ DWORD dwDisposition;
+
+ // open registry key
+
+ lStatus = RegOpenKeyEx (
+ HKEY_LOCAL_MACHINE,
+ TEXT("System\\CurrentControlSet\\Services\\PerfDataLog"),
+ 0,
+ KEY_READ | KEY_WRITE,
+ &hKeyPerfLog);
+ ASSERT (lStatus == ERROR_SUCCESS);
+ if (lStatus != ERROR_SUCCESS) goto Close_And_Exit;
+
+ // add registry subkeys for Log Queries
+ lStatus = RegCreateKeyEx (
+ hKeyPerfLog,
+ TEXT("Log Queries"),
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ | KEY_WRITE,
+ NULL,
+ &hKeyLogQueries,
+ &dwDisposition);
+ ASSERT (lStatus == ERROR_SUCCESS);
+ if (lStatus != ERROR_SUCCESS) goto Close_And_Exit;
+
+ lStatus = RegCreateKeyEx (
+ hKeyLogQueries,
+ TEXT("Default"),
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ | KEY_WRITE,
+ NULL,
+ &hKeyLogQueriesDefault,
+ &dwDisposition);
+ ASSERT (lStatus == ERROR_SUCCESS);
+ if (lStatus != ERROR_SUCCESS) goto Close_And_Exit;
+
+ // open registry key
+ lStatus = RegOpenKeyEx (
+ HKEY_LOCAL_MACHINE,
+ TEXT("System\\CurrentControlSet\\Services\\EventLog\\Application"),
+ 0,
+ KEY_READ | KEY_WRITE,
+ &hKeyEventLogApplication);
+ ASSERT (lStatus == ERROR_SUCCESS);
+ if (lStatus != ERROR_SUCCESS) goto Close_And_Exit;
+
+ // add registry subkeys for event log
+
+ lStatus = RegCreateKeyEx (
+ hKeyEventLogApplication,
+ TEXT("PerfDataLog"),
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ | KEY_WRITE,
+ NULL,
+ &hKeyEventLogPerfDataLog,
+ &dwDisposition);
+ ASSERT (lStatus == ERROR_SUCCESS);
+ if (lStatus != ERROR_SUCCESS) goto Close_And_Exit;
+
+ lStatus = RegSetValueEx (hKeyEventLogPerfDataLog,
+ TEXT("EventMessageFile"),
+ 0,
+ REG_SZ,
+ (BYTE *)TEXT("%systemroot%\\system32\\pdlsvc.exe"),
+ (lstrlen(TEXT("%systemroot%\\system32\\pdlsvc.exe"))+1) * sizeof (TCHAR));
+ ASSERT (lStatus == ERROR_SUCCESS);
+ if (lStatus != ERROR_SUCCESS) goto Close_And_Exit;
+
+ dwValue = 7;
+ lStatus = RegSetValueEx (hKeyEventLogPerfDataLog,
+ TEXT("TypesSupported"),
+ 0,
+ REG_DWORD,
+ (BYTE *)&dwValue,
+ sizeof (DWORD));
+ ASSERT (lStatus == ERROR_SUCCESS);
+ if (lStatus != ERROR_SUCCESS) goto Close_And_Exit;
+
+Close_And_Exit:
+
+ if (hKeyPerfLog != NULL) RegCloseKey (hKeyPerfLog);
+ if (hKeyLogQueries != NULL) RegCloseKey (hKeyLogQueries);
+ if (hKeyLogQueriesDefault != NULL) RegCloseKey (hKeyLogQueriesDefault);
+
+ if (hKeyEventLogApplication != NULL) RegCloseKey (hKeyEventLogApplication);
+ if (hKeyEventLogPerfDataLog != NULL) RegCloseKey (hKeyEventLogPerfDataLog);
+
+ return lStatus;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CPdlConfigApp initialization
+
+BOOL CPdlConfigApp::InitInstance()
+{
+ LONG lServiceStatus;
+ CString csMessage;
+ BOOL bReturn = TRUE;
+
+ // Standard initialization
+ // If you are not using these features and wish to reduce the size
+ // of your final executable, you should remove from the following
+ // the specific initialization routines you do not need.
+
+#ifdef _AFXDLL
+ Enable3dControls(); // Call this when using MFC in a shared DLL
+#else
+ Enable3dControlsStatic(); // Call this when linking to MFC statically
+#endif
+
+ lServiceStatus = PerfLogServiceStatus();
+
+ if (lServiceStatus == ERROR_FILE_NOT_FOUND) {
+ lServiceStatus = ServiceFilesCopied();
+ if (lServiceStatus == ERROR_SUCCESS) {
+ if (AfxMessageBox (IDS_QUERY_INSTALL,
+ MB_OKCANCEL | MB_ICONQUESTION) == IDOK) {
+ lServiceStatus = CreatePerfDataLogService();
+ if (lServiceStatus == ERROR_SUCCESS) {
+ lServiceStatus = InitPerfDataLogRegistry();
+ }
+ if (lServiceStatus != ERROR_SUCCESS) {
+ csMessage.FormatMessage (lServiceStatus);
+ AfxMessageBox (csMessage);
+ bReturn = FALSE;
+ }
+ } else {
+ // the service is not installed and the user doesn't
+ // want it installed so exit
+ bReturn = FALSE;
+ }
+ } else {
+ // then the service has not yet been installed so bail
+ AfxMessageBox (IDS_SERVICE_NOT_INSTALLED);
+ bReturn = FALSE;
+ }
+ } else if (lServiceStatus == ERROR_ACCESS_DENIED) {
+ AfxMessageBox (IDS_ACCESS_DENIED, MB_OK | MB_ICONEXCLAMATION);
+ bReturn = FALSE;
+ } else if (lServiceStatus != ERROR_SUCCESS) {
+ AfxMessageBox (IDS_REGISTRY_ERROR, MB_OK | MB_ICONEXCLAMATION);
+ bReturn = FALSE;
+ } else {
+ bReturn = TRUE;
+ }
+
+ if (bReturn) {
+ CPropertySheet PSheet;
+ COutputPropPage POutput;
+ CSettingsPropPage PSettings;
+
+ m_pMainWnd = &PSheet;
+
+ csMessage.LoadString (IDS_PROPERTY_SHEET_CAPTION);
+ PSheet.SetTitle(csMessage);
+ PSheet.AddPage(&PSettings);
+ PSheet.AddPage(&POutput);
+
+ int nResponse = PSheet.DoModal();
+ if (nResponse == IDOK)
+ {
+ // TODO: Place code here to handle when the dialog is
+ // dismissed with OK
+ }
+ else if (nResponse == IDCANCEL)
+ {
+ // TODO: Place code here to handle when the dialog is
+ // dismissed with Cancel
+ }
+ bReturn = FALSE;
+ }
+
+ // Since the dialog has been closed, return FALSE so that we exit the
+ // application, rather than start the application's message pump.
+ return bReturn;
+}
diff --git a/private/sdktools/perflog/pdlcnfig/pdlcnfig.h b/private/sdktools/perflog/pdlcnfig/pdlcnfig.h
new file mode 100644
index 000000000..2fd5b032c
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/pdlcnfig.h
@@ -0,0 +1,47 @@
+// pdlcnfig.h : main header file for the pdlcnfig application
+//
+#ifndef _PDLCNFIG_H_
+#define _PDLCNFIG_H_
+#ifndef __AFXWIN_H__
+ #error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include <tchar.h>
+#include "resource.h" // main symbols
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CPdlConfigApp:
+// See PDLCNFIG.cpp for the implementation of this class
+//
+
+class CPdlConfigApp : public CWinApp
+{
+public:
+ CPdlConfigApp();
+
+ LONG PerfLogServiceStatus();
+ LONG ServiceFilesCopied();
+ LONG CreatePerfDataLogService ();
+ LONG InitPerfDataLogRegistry ();
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CPdlConfigApp)
+ public:
+ virtual BOOL InitInstance();
+ //}}AFX_VIRTUAL
+
+// Implementation
+
+ //{{AFX_MSG(CPdlConfigApp)
+ // NOTE - the ClassWizard will add and remove member functions here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // _PDLCNFIG_H_
+
diff --git a/private/sdktools/perflog/pdlcnfig/pdlcnfig.ico b/private/sdktools/perflog/pdlcnfig/pdlcnfig.ico
new file mode 100644
index 000000000..7eef0bcbe
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/pdlcnfig.ico
Binary files differ
diff --git a/private/sdktools/perflog/pdlcnfig/pdlcnfig.rc b/private/sdktools/perflog/pdlcnfig/pdlcnfig.rc
new file mode 100644
index 000000000..70e01f16e
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/pdlcnfig.rc
@@ -0,0 +1,457 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "#ifdef _WIN32\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#pragma code_page(1252)\r\n"
+ "#endif\r\n"
+ "#include ""afxres.rc"" // Standard components\r\n"
+ "#endif\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME ICON DISCARDABLE "pdlcnfig.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 217, 55
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About Log Service"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ ICON IDR_MAINFRAME,IDC_STATIC,11,17,18,20
+ LTEXT "Performance Data Logging Service Version 1.0",
+ IDC_STATIC,40,10,115,19,SS_NOPREFIX
+ LTEXT "Copyright © 1996",IDC_STATIC,39,34,119,8
+ DEFPUSHBUTTON "OK",IDOK,178,7,32,14,WS_GROUP
+END
+
+IDD_SETTINGS_PAGE DIALOG DISCARDABLE 0, 0, 235, 156
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Log Settings"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Sample &Interval:",IDC_SAMPLE_INTERVAL_CAPTION,123,28,
+ 52,9
+ EDITTEXT IDC_INTERVAL_TIME,123,40,25,12,ES_AUTOHSCROLL |
+ ES_NUMBER
+ CONTROL "Spin1",IDC_INTERVAL_SPIN,"msctls_updown32",
+ UDS_ARROWKEYS,149,40,11,12
+ LTEXT "&Counters:",IDC_COUNTER_LIST_CAPTION,7,55,37,8
+ LISTBOX IDC_COUNTER_LIST,7,65,221,62,LBS_SORT |
+ LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL |
+ WS_HSCROLL | WS_TABSTOP
+ PUSHBUTTON "&Add...",IDC_BROWSE_COUNTERS,59,134,50,15
+ PUSHBUTTON "&Remove",IDC_REMOVE,125,135,50,14
+ GROUPBOX "Service Start",IDC_SERVICE_START_GROUP,7,7,107,45
+ CONTROL "&Automatic",IDC_SERVICE_AUTO,"Button",
+ BS_AUTORADIOBUTTON,15,20,47,10
+ CONTROL "&Manual",IDC_SERVICE_MAN,"Button",BS_AUTORADIOBUTTON,15,
+ 35,45,10
+ PUSHBUTTON "&Start",IDC_MAN_START,68,17,40,12
+ PUSHBUTTON "Sto&p",IDC_MAN_STOP,68,33,40,12
+ COMBOBOX IDC_INTERVAL_UNITS,163,40,53,42,CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Remove Service",IDC_REMOVE_SERVICE,167,8,61,12,NOT
+ WS_VISIBLE | WS_DISABLED | NOT WS_TABSTOP
+END
+
+IDD_OUTPUT_PAGE DIALOG DISCARDABLE 0, 0, 235, 156
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Log File"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Log File Format: ",IDC_FILE_TYPE_CAPTION,7,9,53,9
+ COMBOBOX IDC_LOG_FILETYPE,75,7,153,56,CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | WS_VSCROLL | WS_TABSTOP
+ CONTROL "&Manual Filename Assignment",IDC_MANUAL_NAME,"Button",
+ BS_AUTORADIOBUTTON,7,23,112,10
+ CONTROL "&Automatic Filename Assignment",IDC_AUTOMATIC_NAME,
+ "Button",BS_AUTORADIOBUTTON,7,60,119,10
+ GROUPBOX " Output &Filename ",IDC_MANUAL_NAME_GROUP,19,32,209,25
+ EDITTEXT IDC_OUTPUT_FILE_EDIT,23,41,182,12,ES_AUTOHSCROLL
+ PUSHBUTTON "...",IDC_BROWSE_OUTPUT_FILE,206,41,15,12
+ GROUPBOX "",IDC_AUTO_NAME_GROUP,19,71,209,78
+ LTEXT "&Rename output file every:",IDC_RENAME_INTERVAL_CAPTION,
+ 27,78,83,8
+ EDITTEXT IDC_RENAME_INTERVAL,112,76,23,12,ES_AUTOHSCROLL |
+ ES_OEMCONVERT | ES_NUMBER
+ CONTROL "Spin1",IDC_SPIN_RENAME_INTERVAL,"msctls_updown32",
+ UDS_ARROWKEYS,135,76,11,12
+ COMBOBOX IDC_RENAME_UNITS,150,76,58,51,CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "&Log Folder...",IDC_BROWSE_FOLDER,27,92,45,12
+ LTEXT "IDC_LOG_DIRECTORY",IDC_LOG_DIRECTORY,75,93,150,11,
+ SS_SUNKEN
+ LTEXT "Base &Filename:",IDC_BASE_NAME_CAPTION,27,107,56,8
+ EDITTEXT IDC_BASE_FILENAME_EDIT,27,117,120,12,ES_AUTOHSCROLL
+ LTEXT "Au&to Format:",IDC_AUTO_NAME_CAPTION,157,107,48,8
+ COMBOBOX IDC_AUTO_NAME_COMBO,156,117,65,48,CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Example:",IDC_SAMPLE_NAME,27,135,32,10
+ LTEXT "IDC_SAMPLE_NAME_TEXT",IDC_SAMPLE_NAME_TEXT,60,135,165,
+ 10,SS_SUNKEN
+END
+
+IDD_ALARM_SETTINGS_PAGE DIALOG DISCARDABLE 0, 0, 235, 156
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Alert Settings"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ PUSHBUTTON "&Edit...",IDC_EDIT_BUTTON,92,134,50,15
+ LTEXT "Sample &Interval:",IDC_SAMPLE_INTERVAL_CAPTION,123,28,
+ 52,9
+ EDITTEXT IDC_INTERVAL_TIME,123,40,25,12,ES_AUTOHSCROLL |
+ ES_NUMBER
+ CONTROL "Spin1",IDC_INTERVAL_SPIN,"msctls_updown32",
+ UDS_ARROWKEYS,149,40,11,12
+ LTEXT "&Counters:",IDC_COUNTER_LIST_CAPTION,7,55,37,8
+ LISTBOX IDC_COUNTER_LIST,7,65,221,62,LBS_SORT |
+ LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL |
+ WS_HSCROLL | WS_TABSTOP
+ PUSHBUTTON "&Add...",IDC_BROWSE_COUNTERS,26,134,50,15
+ PUSHBUTTON "&Remove",IDC_REMOVE,158,135,50,14
+ GROUPBOX "Service Start",IDC_SERVICE_START_GROUP,7,7,107,45
+ CONTROL "&Automatic",IDC_SERVICE_AUTO,"Button",
+ BS_AUTORADIOBUTTON,15,20,47,10
+ CONTROL "&Manual",IDC_SERVICE_MAN,"Button",BS_AUTORADIOBUTTON,15,
+ 35,45,10
+ PUSHBUTTON "&Start",IDC_MAN_START,68,17,40,12
+ PUSHBUTTON "Sto&p",IDC_MAN_STOP,68,33,40,12
+ COMBOBOX IDC_INTERVAL_UNITS,163,40,53,42,CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_ALARM_OPTIONS_PAGE DIALOG DISCARDABLE 0, 0, 235, 156
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Alert Options"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CONTROL "Log Alerts In Application Event Log",
+ IDC_LOG_TO_EVENTLOG,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,7,7,176,11
+ CONTROL "Log Alerts To Text File",IDC_LOG_ALARM_TO_FILE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,7,24,188,11
+ LTEXT "Alert Log Filename:",IDC_ALARM_LOG_FILE_CAPTION,21,37,
+ 130,8
+ EDITTEXT IDC_ALARM_LOG_FILE_EDIT,23,45,160,12,ES_AUTOHSCROLL
+ PUSHBUTTON "Browse...",IDC_BROWSE_ALARM_LOG,183,45,45,12
+ CONTROL "Run Program On Every Alert",IDC_RUN_PROGRAM,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,7,63,165,11
+ LTEXT "Program Command Line:",IDC_COMMAND_LINE_CAPTION,21,76,
+ 127,10
+ EDITTEXT IDC_PROGRAM_COMMAND_LINE,21,86,207,12,ES_AUTOHSCROLL
+ GROUPBOX "Execute Command",IDC_RUN_PROGRAM_GROUP,23,103,72,46
+ CONTROL "Every Time",IDC_CMD_EVERY_TIME,"Button",
+ BS_AUTORADIOBUTTON | WS_GROUP,30,115,50,11
+ CONTROL "First Time Only",IDC_CMD_FIRST_TIME,"Button",
+ BS_AUTORADIOBUTTON,30,130,63,11
+ GROUPBOX "Command Line Parameters",IDC_COMMAND_LINE_OPTIONS,101,
+ 103,127,46,WS_GROUP
+ CONTROL "Counter Name",IDC_CMD_ARG_NAME,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,107,115,63,10
+ CONTROL "Counter Value",IDC_CMD_ARG_VALUE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,107,130,59,9
+ CONTROL "Threshold",IDC_CMD_ARG_LIMIT,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,172,115,49,11
+ CONTROL "Time Stamp",IDC_CMD_ARG_TIME,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,172,130,56,8
+END
+
+IDD_LOG_DIR_BROWSER DIALOG DISCARDABLE 0, 0, 250, 52
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Select Default Log File Folder"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,67,31,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,133,31,50,14
+ EDITTEXT IDC_DIRECTORY_PATH_EDIT,7,7,161,13,ES_AUTOHSCROLL
+ PUSHBUTTON "Browse...",IDC_BROWSE_DIRS,183,7,60,14
+END
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "\0"
+ VALUE "FileDescription", "Perf Data Log Configuration Application\0"
+ VALUE "FileVersion", "1, 0, 0, 1\0"
+ VALUE "InternalName", "PDLCNFIG\0"
+ VALUE "LegalCopyright", "Copyright (c) 1996\0"
+ VALUE "OriginalFilename", "PDLCNFIG.EXE\0"
+ VALUE "ProductName", "Perf Data Log Configuration Application\0"
+ VALUE "ProductVersion", "1, 0, 0, 1\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_ABOUTBOX, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 210
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 48
+ END
+
+ IDD_SETTINGS_PAGE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 228
+ TOPMARGIN, 8
+ BOTTOMMARGIN, 149
+ END
+
+ IDD_OUTPUT_PAGE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 228
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 149
+ END
+
+ IDD_ALARM_SETTINGS_PAGE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 228
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 149
+ END
+
+ IDD_ALARM_OPTIONS_PAGE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 228
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 149
+ END
+
+ IDD_LOG_DIR_BROWSER, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 243
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 45
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog Info
+//
+
+IDD_OUTPUT_PAGE DLGINIT
+BEGIN
+ IDC_LOG_FILETYPE, 0x403, 32, 0
+0x6f43, 0x6d6d, 0x2061, 0x6553, 0x6170, 0x6172, 0x6574, 0x2064, 0x6156,
+0x6972, 0x6261, 0x656c, 0x2820, 0x432e, 0x5653, 0x0029,
+ IDC_LOG_FILETYPE, 0x403, 30, 0
+0x6154, 0x2062, 0x6553, 0x6170, 0x6172, 0x6574, 0x2064, 0x6156, 0x6972,
+0x6261, 0x656c, 0x2820, 0x542e, 0x5653, 0x0029,
+ IDC_RENAME_UNITS, 0x403, 6, 0
+0x6f48, 0x7275, 0x0073,
+ IDC_RENAME_UNITS, 0x403, 5, 0
+0x6144, 0x7379, "\000"
+ IDC_RENAME_UNITS, 0x403, 7, 0
+0x6f4d, 0x746e, 0x7368, "\000"
+ IDC_RENAME_UNITS, 0x403, 10, 0
+0x694b, 0x6f6c, 0x7962, 0x6574, 0x0073,
+ IDC_RENAME_UNITS, 0x403, 10, 0
+0x654d, 0x6167, 0x7962, 0x6574, 0x0073,
+ IDC_AUTO_NAME_COMBO, 0x403, 7, 0
+0x6d6d, 0x6464, 0x6868, "\000"
+ IDC_AUTO_NAME_COMBO, 0x403, 7, 0
+0x6e6e, 0x6e6e, 0x6e6e, "\000"
+ IDC_AUTO_NAME_COMBO, 0x403, 6, 0
+0x7979, 0x6464, 0x0064,
+ IDC_AUTO_NAME_COMBO, 0x403, 5, 0
+0x7979, 0x6d6d, "\000"
+ IDC_AUTO_NAME_COMBO, 0x403, 7, 0
+0x7979, 0x6d6d, 0x6464, "\000"
+ IDC_AUTO_NAME_COMBO, 0x403, 9, 0
+0x7979, 0x6d6d, 0x6464, 0x6868, "\000"
+ 0
+END
+
+IDD_SETTINGS_PAGE DLGINIT
+BEGIN
+ IDC_INTERVAL_UNITS, 0x403, 8, 0
+0x6553, 0x6f63, 0x646e, 0x0073,
+ IDC_INTERVAL_UNITS, 0x403, 8, 0
+0x694d, 0x756e, 0x6574, 0x0073,
+ IDC_INTERVAL_UNITS, 0x403, 6, 0
+0x6f48, 0x7275, 0x0073,
+ IDC_INTERVAL_UNITS, 0x403, 5, 0
+0x6144, 0x7379, "\000"
+ 0
+END
+
+IDD_ALARM_SETTINGS_PAGE DLGINIT
+BEGIN
+ IDC_INTERVAL_UNITS, 0x403, 8, 0
+0x6553, 0x6f63, 0x646e, 0x0073,
+ IDC_INTERVAL_UNITS, 0x403, 8, 0
+0x694d, 0x756e, 0x6574, 0x0073,
+ IDC_INTERVAL_UNITS, 0x403, 6, 0
+0x6f48, 0x7275, 0x0073,
+ IDC_INTERVAL_UNITS, 0x403, 5, 0
+0x6144, 0x7379, "\000"
+ 0
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_ABOUTBOX "&About Perf Data Log..."
+ IDS_SERVICE_NOT_INSTALLED
+ "The Perf Data Log service has not yet been installed. \nReview the documentation and install the software and try again."
+ IDS_PROPERTY_SHEET_CAPTION "Performance Data Log Service"
+ IDS_ACCESS_DENIED "You do not have sufficient privilege to access this service. Contact the system's administrator to access the service."
+ IDS_REGISTRY_ERROR "Unable to read the Performance Data Log service configuration data from the registry. Check the service installation and the registry entries for this service and retry."
+ IDS_MESSAGE_BOX_CAPTION "Performance Log Service Error"
+ IDS_NAME_FORMAT_NOT_COMPATIBLE
+ "The Auto Format string selected if used with the current Rename Interval Units may cause some log files to be overwritten.\n\rDo you want to keep this configuration?"
+ IDS_WARNING "Perf Data Log Warning"
+ IDS_SC_ACCESS_ERROR "Unable to access Service Controller."
+ IDS_SC_CREATE_ERROR "Unable to create Perf Data Logging service."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_SC_INSTALL_ERROR_PERMS
+ "Unable to install the Perf Data Log Service.\r\nInsure you have the necessary permissions and access and retry."
+ IDS_ERROR "Perf Data Log Error"
+ IDS_STOP_AND_START "The Perf Data Log service must be stopped and restarted for these changes to take effect"
+ IDS_NOTICE "Perf Data Log Notice"
+ IDS_REMOVE_SERVICE_WARNING
+ "This will delete the service from the system. Are you sure you want to continue?"
+ IDS_QUERY_INSTALL "The Perf Data Log Service file have been copied, but the service has not been installed. Select OK to install the service now, or Cancel to exit."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ AFX_IDS_APP_TITLE "Perf Data Log Config"
+END
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif
+#include "afxres.rc" // Standard components
+#endif
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
+ \ No newline at end of file
diff --git a/private/sdktools/perflog/pdlcnfig/resource.h b/private/sdktools/perflog/pdlcnfig/resource.h
new file mode 100644
index 000000000..5835110d6
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/resource.h
@@ -0,0 +1,113 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by PDLCNFIG.rc
+//
+#define IDM_ABOUTBOX 0x0010
+
+#define IDD_ABOUTBOX 100
+#define IDD_PDLCNFIG_DIALOG 101
+#define IDD_SETTINGS_PAGE 102
+#define IDD_OUTPUT_PAGE 103
+
+#define IDS_ABOUTBOX 101
+#define IDS_SERVICE_NOT_INSTALLED 102
+#define IDS_PROPERTY_SHEET_CAPTION 103
+#define IDS_ACCESS_DENIED 104
+#define IDS_REGISTRY_ERROR 105
+#define IDS_MESSAGE_BOX_CAPTION 106
+#define IDS_NAME_FORMAT_NOT_COMPATIBLE 107
+#define IDS_WARNING 108
+#define IDS_SC_ACCESS_ERROR 109
+#define IDS_SC_CREATE_ERROR 110
+#define IDS_SC_INSTALL_ERROR_PERMS 111
+#define IDS_ERROR 112
+#define IDS_STOP_AND_START 113
+#define IDS_NOTICE 114
+#define IDS_REMOVE_SERVICE_WARNING 115
+#define IDS_QUERY_INSTALL 116
+
+#define IDR_MAINFRAME 1000
+
+#define IDC_INTERVAL_TIME 1005
+#define IDC_INTERVAL_SPIN 1006
+#define IDC_BROWSE_COUNTERS 1007
+#define IDC_REMOVE 1008
+#define IDC_SERVICE_AUTO 1009
+#define IDC_SERVICE_MAN 1010
+#define IDC_REMOVE_SERVICE 1011
+#define IDC_EDIT 1012
+#define IDC_EDIT_BUTTON 1013
+#define IDC_MANUAL_NAME 1018
+#define IDC_OUTPUT_FILE_EDIT 1019
+#define IDC_BROWSE_OUTPUT_FILE 1020
+#define IDC_AUTOMATIC_NAME 1021
+#define IDC_BASE_FILENAME_EDIT 1022
+#define IDC_AUTO_NAME_COMBO 1023
+#define IDC_SAMPLE_NAME 1024
+#define IDC_RENAME_INTERVAL 1025
+#define IDC_RENAME_UNITS 1026
+#define IDC_SPIN_RENAME_INTERVAL 1027
+#define IDC_BROWSE_BASE_NAME 1028
+#define IDC_BROWSE_FOLDER 1029
+#define IDC_SAMPLE_NAME_TEXT 1030
+#define IDC_COUNTER_LIST 1031
+#define IDC_MAN_START 1033
+#define IDC_MAN_STOP 1034
+#define IDC_MAN_PAUSE 1035
+#define IDC_SERVICE_START_GROUP 1036
+#define IDC_MANUAL_CONTROL_GROUP 1037
+#define IDC_MAN_RESUME 1038
+#define IDC_SAMPLE_INTERVAL_CAPTION 1040
+#define IDC_COUNTER_LIST_CAPTION 1042
+#define IDC_RENAME_INTERVAL_CAPTION 1044
+#define IDC_BASE_NAME_CAPTION 1046
+#define IDC_MAN_FILENAME 1047
+#define IDC_PROGRESS_BAR 1048
+#define IDC_STATUS_TEXT 1049
+#define IDC_MANUAL_NAME_GROUP 1052
+#define IDC_FILE_TYPE_CAPTION 1053
+#define IDC_LOG_FILETYPE 1054
+#define IDC_INTERVAL_UNITS 1055
+#define IDC_AUTO_NAME_GROUP 1056
+#define IDC_AUTO_NAME_CAPTION 1057
+#define IDC_LOG_DIRECTORY 1064
+#define IDC_LOG_ALARM_TO_FILE 1065
+#define IDC_ALARM_LOG_FILE_EDIT 1066
+#define IDC_BROWSE_ALARM_LOG 1067
+#define IDC_LOG_TO_EVENTLOG 1068
+#define IDC_ALARM_LOG_FILE_CAPTION 1069
+#define IDC_RUN_PROGRAM 1070
+#define IDC_PROGRAM_COMMAND_LINE 1071
+#define IDC_COMMAND_LINE_CAPTION 1072
+#define IDC_COMMAND_LINE_OPTIONS 1073
+#define IDC_RUN_PROGRAM_GROUP 1074
+#define IDC_CMD_FIRST_TIME 1075
+#define IDC_CMD_EVERY_TIME 1076
+#define IDC_CMD_ARG_NAME 1077
+#define IDC_CMD_ARG_VALUE 1078
+#define IDC_CMD_ARG_LIMIT 1079
+#define IDC_CMD_ARG_TIME 1080
+#define IDC_LOG_DIRECTORY_CAPTION 1081
+#define IDC_DIRECTORY_PATH_EDIT 1082
+#define IDC_BROWSE_DIRS 1083
+#define IDC_EDIT1 1084
+#define IDC_COUNTER_PATH_EDIT 1084
+#define IDC_BUTTON1 1085
+#define IDC_OVER 1086
+#define IDC_UNDER 1087
+#define IDC_THRESHOLD 1088
+#define IDC_INFO_ALERT 1089
+#define IDC_WARNING_ALERT 1090
+#define IDC_ERROR_ALERT 1091
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 142
+#define _APS_NEXT_COMMAND_VALUE 32771
+#define _APS_NEXT_CONTROL_VALUE 1092
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
+
diff --git a/private/sdktools/perflog/pdlcnfig/setpage.cpp b/private/sdktools/perflog/pdlcnfig/setpage.cpp
new file mode 100644
index 000000000..0be4cb062
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/setpage.cpp
@@ -0,0 +1,974 @@
+// SettingsPage.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "pdlcnfig.h"
+#include "SetPage.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CSettingsPropPage property page
+
+IMPLEMENT_DYNCREATE(CSettingsPropPage, CPropertyPage)
+
+CSettingsPropPage::CSettingsPropPage() : CPropertyPage(CSettingsPropPage::IDD)
+{
+ //{{AFX_DATA_INIT(CSettingsPropPage)
+ m_IntervalTime = 0;
+ m_SettingsFile = _T("");
+ m_IntervalUnitsIndex = -1;
+ //}}AFX_DATA_INIT
+
+ m_hKeyLogSettingsDefault = NULL;
+ m_hKeyLogService = NULL;
+ // counter buffer
+ m_szCounterListBuffer = NULL;
+ m_dwCounterListBufferSize = 0;
+ // list box information
+ m_dwMaxHorizListExtent = 0;
+ // prototype use only
+ bServiceStopped = TRUE;
+ bServicePaused = FALSE;
+}
+
+CSettingsPropPage::~CSettingsPropPage()
+{
+ if (m_hKeyLogSettingsDefault != NULL) RegCloseKey(m_hKeyLogSettingsDefault);
+ if (m_hKeyLogService != NULL) RegCloseKey(m_hKeyLogService);
+}
+
+void CSettingsPropPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CSettingsPropPage)
+ DDX_Text(pDX, IDC_INTERVAL_TIME, m_IntervalTime);
+ DDX_CBIndex(pDX, IDC_INTERVAL_UNITS, m_IntervalUnitsIndex);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CSettingsPropPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CSettingsPropPage)
+ ON_BN_CLICKED(IDC_BROWSE_COUNTERS, OnBrowseCounters)
+ ON_BN_CLICKED(IDC_MAN_START, OnManStart)
+ ON_BN_CLICKED(IDC_MAN_STOP, OnManStop)
+ ON_BN_CLICKED(IDC_REMOVE, OnRemove)
+ ON_BN_CLICKED(IDC_SERVICE_AUTO, OnServiceAuto)
+ ON_BN_CLICKED(IDC_SERVICE_MAN, OnServiceMan)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_INTERVAL_SPIN, OnDeltaposIntervalSpin)
+ ON_CBN_SELCHANGE(IDC_INTERVAL_UNITS, OnSelchangeIntervalUnits)
+ ON_BN_CLICKED(IDC_REMOVE_SERVICE, OnRemoveService)
+ ON_EN_CHANGE(IDC_INTERVAL_TIME, OnChangeIntervalTime)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CSettingsPropPage Helper Functions
+
+
+
+LONG CSettingsPropPage::SetCurrentServiceState (DWORD dwNewState)
+{
+ SC_HANDLE hSC = NULL;
+ SC_HANDLE hService = NULL;
+ SERVICE_STATUS ssData;
+ DWORD dwTimeout = 20;
+ BOOL bStopped, bPaused;
+ LONG lStatus;
+ HCURSOR hOrigCursor;
+
+ hOrigCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
+
+ // open SC database
+ hSC = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (hSC == NULL) {
+ lStatus = GetLastError();
+ ASSERT (lStatus != ERROR_SUCCESS);
+ }
+ // open service
+ hService = OpenService (hSC, TEXT("PerfDataLog"),
+ SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE);
+
+ if (hService != NULL) {
+ switch (dwNewState) {
+ case LOG_SERV_START:
+ StartService (hService, 0, NULL);
+ // wait for the service to start before returning
+ while (--dwTimeout) {
+ GetCurrentServiceState (&bStopped, &bPaused);
+ if (bStopped) {
+ Sleep(500);
+ } else {
+ break;
+ }
+ }
+ break;
+
+ case LOG_SERV_STOP:
+ ControlService (hService, SERVICE_CONTROL_STOP, &ssData);
+ // wait for the service to stop before returning
+ while (--dwTimeout) {
+ GetCurrentServiceState (&bStopped, &bPaused);
+ if (!bStopped) {
+ Sleep(500);
+ } else {
+ break;
+ }
+ }
+ break;
+
+ case LOG_SERV_PAUSE:
+ ControlService (hService, SERVICE_CONTROL_PAUSE, &ssData);
+ // wait for the service to start pause returning
+ while (--dwTimeout) {
+ GetCurrentServiceState (&bStopped, &bPaused);
+ if (!bPaused) {
+ Sleep(500);
+ } else {
+ break;
+ }
+ }
+ break;
+
+ case LOG_SERV_RESUME:
+ ControlService (hService, SERVICE_CONTROL_CONTINUE, &ssData);
+ // wait for the service to start before returning
+ while (--dwTimeout) {
+ GetCurrentServiceState (&bStopped, &bPaused);
+ if (bPaused) {
+ Sleep(500);
+ } else {
+ break;
+ }
+ }
+ break;
+
+ default:
+ // no change if not recognized
+ break;
+ }
+ CloseServiceHandle (hService);
+ } else {
+ lStatus = GetLastError();
+ ASSERT (lStatus != 0);
+ }
+ // close handles
+ if (hSC != NULL) CloseServiceHandle (hSC);
+
+ ::SetCursor (hOrigCursor);
+
+ return ERROR_SUCCESS;
+}
+
+LONG CSettingsPropPage::GetCurrentServiceState (BOOL * bStopped, BOOL * bPaused)
+{
+ SC_HANDLE hSC = NULL;
+ SC_HANDLE hService = NULL;
+ SERVICE_STATUS ssData;
+ LONG lStatus;
+ HCURSOR hOrigCursor;
+
+ BOOL bServiceStopped, bServicePaused;
+
+ hOrigCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
+
+ // open SC database
+ hSC = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (hSC == NULL) {
+ lStatus = GetLastError();
+ ASSERT (lStatus != ERROR_SUCCESS);
+ }
+ // open service
+ hService = OpenService (hSC, TEXT("PerfDataLog"), SERVICE_INTERROGATE);
+ // get service status
+
+ if (hService != NULL) {
+ if (ControlService (
+ hService, SERVICE_CONTROL_INTERROGATE,
+ &ssData)) {
+ switch (ssData.dwCurrentState) {
+ case SERVICE_STOPPED:
+ bServiceStopped = TRUE;
+ bServicePaused = FALSE;
+ break;
+
+ case SERVICE_START_PENDING:
+ bServiceStopped = TRUE;
+ bServicePaused = FALSE;
+ break;
+
+ case SERVICE_STOP_PENDING:
+ bServiceStopped = FALSE;
+ bServicePaused = FALSE;
+ break;
+
+ case SERVICE_RUNNING:
+ bServiceStopped = FALSE;
+ bServicePaused = FALSE;
+ break;
+
+ case SERVICE_CONTINUE_PENDING:
+ bServiceStopped = FALSE;
+ bServicePaused = FALSE;
+ break;
+
+ case SERVICE_PAUSE_PENDING:
+ bServiceStopped = FALSE;
+ bServicePaused = FALSE;
+ break;
+
+ case SERVICE_PAUSED:
+ bServiceStopped = FALSE;
+ bServicePaused = TRUE;
+ break;
+
+ default:
+ ;// no op
+ }
+ } else {
+ bServiceStopped = TRUE;
+ bServicePaused = TRUE;
+ }
+ CloseServiceHandle (hService);
+ } else {
+ lStatus = GetLastError();
+ ASSERT (lStatus != 0);
+ }
+
+ *bStopped = bServiceStopped;
+ *bPaused = bServicePaused;
+
+ // close handles
+ if (hSC != NULL) CloseServiceHandle (hSC);
+
+ ::SetCursor (hOrigCursor);
+
+ return ERROR_SUCCESS;
+}
+
+UINT
+ConnectMachineThreadProc (LPVOID lpArg)
+{
+ return PdhConnectMachine (NULL);
+}
+
+LONG CSettingsPropPage::SyncServiceStartWithButtons(void)
+{
+ SC_HANDLE hSC = NULL;
+ SC_HANDLE hService = NULL;
+ DWORD dwMoreBytes = 0;
+ BOOL bManualEnabled = FALSE;
+ BOOL bUpdate = FALSE;
+ LONG lStatus;
+
+ QUERY_SERVICE_CONFIG qsConfig;
+ HCURSOR hOrigCursor;
+
+ hOrigCursor = ::SetCursor(LoadCursor(NULL, IDC_WAIT));
+
+ // get button state
+ if (IsDlgButtonChecked(IDC_SERVICE_MAN)) {
+ bManualEnabled = TRUE;
+ }
+
+ // open SC database
+ hSC = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (hSC == NULL) {
+ lStatus = GetLastError();
+ ASSERT (lStatus != ERROR_SUCCESS);
+ }
+ // open service
+ hService = OpenService (hSC, TEXT("PerfDataLog"),
+ SERVICE_CHANGE_CONFIG | SERVICE_QUERY_CONFIG);
+
+ if (hService != NULL) {
+ // get current config
+ memset (&qsConfig, 0, sizeof(qsConfig));
+ if (QueryServiceConfig (hService, &qsConfig,
+ sizeof(qsConfig), &dwMoreBytes)) {
+ // see if the current status is different
+ // from the selection. if it is, then change
+ // the current mode.
+ if (bManualEnabled) {
+ if (qsConfig.dwStartType == SERVICE_AUTO_START) {
+ bUpdate = TRUE;
+ }
+ } else {
+ // auto start selected
+ if (qsConfig.dwStartType == SERVICE_DEMAND_START) {
+ bUpdate = TRUE;
+ }
+ }
+ } else {
+ // else unable to read the current status so update anyway
+ bUpdate = TRUE;
+ }
+
+ if (bUpdate) {
+ ChangeServiceConfig (
+ hService,
+ SERVICE_NO_CHANGE,
+ (bManualEnabled ? SERVICE_DEMAND_START : SERVICE_AUTO_START),
+ SERVICE_NO_CHANGE,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ }
+ CloseServiceHandle (hService);
+ } else {
+ lStatus = GetLastError();
+ ASSERT (lStatus != 0);
+ }
+
+ // close handles
+ if (hSC != NULL) CloseServiceHandle (hSC);
+
+ ::SetCursor (hOrigCursor);
+
+ return ERROR_SUCCESS;
+}
+
+
+void CSettingsPropPage::UpdateManualButtonsState()
+{
+ BOOL bServiceIsStopped;
+ BOOL bServiceIsPaused;
+
+ LONG lStatus;
+ BOOL bManualEnabled;
+ if (IsDlgButtonChecked(IDC_SERVICE_AUTO)) {
+ bManualEnabled = FALSE;
+ } else if (IsDlgButtonChecked(IDC_SERVICE_MAN)) {
+ bManualEnabled = TRUE;
+ } else {
+ // if no button is checked, then check the auto
+ // button and continue
+ CheckRadioButton (IDC_SERVICE_AUTO, IDC_SERVICE_MAN, IDC_SERVICE_AUTO);
+ bManualEnabled = FALSE;
+ }
+
+ GetDlgItem(IDC_MAN_START)->EnableWindow(bManualEnabled);
+ GetDlgItem(IDC_MAN_STOP)->EnableWindow(bManualEnabled);
+
+ if (bManualEnabled) {
+ // check with service controller to get the current state of the service
+
+ lStatus = GetCurrentServiceState (&bServiceIsStopped, &bServiceIsPaused);
+ GetDlgItem(IDC_MAN_START)->EnableWindow(bServiceIsStopped);
+ GetDlgItem(IDC_MAN_STOP)->EnableWindow(!bServiceIsStopped);
+ }
+}
+
+static void DialogCallBack(CSettingsPropPage *pDlg)
+{
+ // add strings in buffer to list box
+ LPTSTR NewCounterName;
+ LRESULT lIndex;
+ PDH_STATUS pdhStatus;
+ CListBox *cCounterList;
+ DWORD dwItemExtent;
+
+ cCounterList = (CListBox *)pDlg->GetDlgItem(IDC_COUNTER_LIST);
+
+ for (NewCounterName = pDlg->m_szCounterListBuffer;
+ *NewCounterName != 0;
+ NewCounterName += (lstrlen(NewCounterName) + 1)) {
+ if (_tcsstr (NewCounterName, TEXT("*")) == NULL) {
+ pdhStatus = PdhValidatePath(NewCounterName);
+ } else {
+ // assume wild cards are valid for now
+ pdhStatus = ERROR_SUCCESS;
+ }
+ if (pdhStatus == ERROR_SUCCESS) {
+ // this is a valid counter so add it to the list
+ lIndex = cCounterList->AddString(NewCounterName);
+ // select the current entry in the list box
+ if (lIndex != LB_ERR) {
+ // update list box extent
+ dwItemExtent = (DWORD)((cCounterList->GetDC())->GetTextExtent (NewCounterName)).cx;
+ if (dwItemExtent > pDlg->m_dwMaxHorizListExtent) {\
+ pDlg->m_dwMaxHorizListExtent = dwItemExtent;
+ cCounterList->SetHorizontalExtent(dwItemExtent);
+ }
+ cCounterList->SetSel (-1, FALSE); // cancel existing selections
+ cCounterList->SetSel (lIndex);
+ cCounterList->SetCaretIndex (lIndex);
+ }
+ } else {
+ MessageBeep (MB_ICONEXCLAMATION);
+ }
+ }
+ // clear buffer
+ memset (pDlg->m_szCounterListBuffer, 0, pDlg->m_dwCounterListBufferSize);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CSettingsPropPage message handlers
+
+BOOL CSettingsPropPage::OnInitDialog()
+{
+ LONG lStatus;
+ DWORD dwRegValType;
+ DWORD dwRegValue;
+ DWORD dwRegValueSize;
+ DWORD dwIndex;
+ LPTSTR mszCounterPathList;
+ LPTSTR szThisCounterPath;
+ CListBox *cCounterList;
+ DWORD dwItemExtent;
+
+ // start machine connection thread to make initial "ADD" dialog
+ // "snappier"
+
+// AfxBeginThread ((AFX_THREADPROC)ConnectMachineThreadProc, NULL);
+
+ // open registry key to service
+ lStatus = RegOpenKeyEx (
+ HKEY_LOCAL_MACHINE,
+ TEXT("SYSTEM\\CurrentControlSet\\Services\\PerfDataLog"),
+ 0,
+ KEY_READ | KEY_WRITE,
+ &m_hKeyLogService);
+
+ // open registry to default log query
+ lStatus = RegOpenKeyEx (
+ m_hKeyLogService,
+ TEXT("Log Queries\\Default"),
+ 0,
+ KEY_READ | KEY_WRITE,
+ &m_hKeyLogSettingsDefault);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // display error, close dialog and exit
+ }
+ // continue
+ // initialize the service state
+
+ dwRegValType = 0;
+ dwRegValue = 0;
+ dwRegValueSize = sizeof(DWORD);
+ lStatus = RegQueryValueEx (
+ m_hKeyLogService,
+ TEXT("Start"),
+ NULL,
+ &dwRegValType,
+ (LPBYTE)&dwRegValue,
+ &dwRegValueSize);
+
+ if ((lStatus == ERROR_SUCCESS) &&
+ (dwRegValType == REG_DWORD) &&
+ (dwRegValue == SERVICE_DEMAND_START)) {
+ // then set manual control
+ CheckRadioButton (IDC_SERVICE_AUTO,
+ IDC_SERVICE_MAN, IDC_SERVICE_MAN);
+ } else {
+ // set automatic control (default)
+ CheckRadioButton (IDC_SERVICE_AUTO,
+ IDC_SERVICE_MAN, IDC_SERVICE_AUTO);
+ }
+
+ // set manual buttons to reflect current state of control
+ UpdateManualButtonsState();
+
+ // set sample time
+
+ dwRegValType = 0;
+ dwRegValue = 0;
+ dwRegValueSize = sizeof(DWORD);
+ lStatus = RegQueryValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Sample Interval"),
+ NULL,
+ &dwRegValType,
+ (LPBYTE)&dwRegValue,
+ &dwRegValueSize);
+
+ if ((lStatus == ERROR_SUCCESS) &&
+ (dwRegValType == REG_DWORD)) {
+ if ((dwRegValue % SECONDS_IN_DAY) == 0) {
+ // then this is in days so scale
+ dwRegValue /= SECONDS_IN_DAY;
+ dwIndex = SIU_DAYS;
+ } else if ((dwRegValue % SECONDS_IN_HOUR) == 0) {
+ // scale to hours
+ dwRegValue /= SECONDS_IN_HOUR;
+ dwIndex = SIU_HOURS;
+ } else if ((dwRegValue % SECONDS_IN_MINUTE) == 0) {
+ // scale to minutes
+ dwRegValue /= SECONDS_IN_MINUTE;
+ dwIndex = SIU_MINUTES;
+ } else {
+ // use as seconds
+ dwIndex = SIU_SECONDS;
+ }
+ // check for zero values & apply default if found
+ if (dwRegValue == 0) {
+ dwRegValue = 15; // default is 15 sec.
+ dwIndex = SIU_SECONDS;
+ }
+ } else {
+ // load default values
+ dwRegValue = 15;
+ dwIndex = SIU_SECONDS;
+ }
+ m_IntervalTime = dwRegValue;
+ m_IntervalUnitsIndex = dwIndex;
+
+ // load counter list box
+ GetDlgItem(IDC_COUNTER_LIST)->SendMessage(LB_RESETCONTENT, 0, 0);
+ // read path string from registry
+
+ // find out buffer size required
+ dwRegValType = 0;
+ dwRegValue = 0;
+ dwRegValueSize = 0;
+ lStatus = RegQueryValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Counter List"),
+ NULL,
+ &dwRegValType,
+ NULL,
+ &dwRegValueSize);
+
+ cCounterList = (CListBox *)GetDlgItem(IDC_COUNTER_LIST);
+ if (dwRegValueSize > 0) {
+ // allocate buffer
+ mszCounterPathList = new TCHAR[dwRegValueSize/sizeof(TCHAR)];
+ ASSERT (mszCounterPathList != NULL);
+
+ *mszCounterPathList = 0;
+ dwRegValType = 0;
+ dwRegValue = 0;
+ lStatus = RegQueryValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Counter List"),
+ NULL,
+ &dwRegValType,
+ (LPBYTE)mszCounterPathList,
+ &dwRegValueSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // assign a MSZ termination
+ mszCounterPathList[0] = 0;
+ mszCounterPathList[1] = 0;
+ }
+
+ // load list box.
+ dwIndex = 0;
+ cCounterList->ResetContent();
+ for (szThisCounterPath = mszCounterPathList;
+ *szThisCounterPath != 0;
+ szThisCounterPath += lstrlen(szThisCounterPath)+1) {
+ lStatus = cCounterList->AddString (szThisCounterPath);
+ if (lStatus != LB_ERR) {
+ dwItemExtent = (DWORD)((cCounterList->GetDC())->GetTextExtent (szThisCounterPath)).cx;
+ if (dwItemExtent > m_dwMaxHorizListExtent) {
+ m_dwMaxHorizListExtent = dwItemExtent;
+ cCounterList->SetHorizontalExtent(dwItemExtent);
+ }
+ dwIndex++;
+ }
+ }
+ cCounterList->SetSel(dwIndex-1);
+ cCounterList->SetCaretIndex(dwIndex-1);
+
+ delete mszCounterPathList;
+ } else {
+ // no counters presently in the list so just initialize everything
+ cCounterList->ResetContent();
+ }
+
+ // select first counter in list (if present)
+ if (GetDlgItem(IDC_COUNTER_LIST)->SendMessage(LB_GETCOUNT) > 0) {
+ GetDlgItem(IDC_COUNTER_LIST)->SendMessage(LB_SETCURSEL, 0, 0);
+ // highlight remove button if an item is selected
+ GetDlgItem(IDC_REMOVE)->EnableWindow (TRUE);
+ } else {
+ GetDlgItem(IDC_REMOVE)->EnableWindow (FALSE);
+ }
+
+ CPropertyPage::OnInitDialog();
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CSettingsPropPage::OnBrowseCounters()
+{
+ PDH_BROWSE_DLG_CONFIG dlgConfig;
+ CListBox *cCounterList;
+ LONG lBeforeCount;
+ LONG lAfterCount;
+
+ if (m_szCounterListBuffer == NULL) {
+ m_dwCounterListBufferSize = 16384;
+ m_szCounterListBuffer = new TCHAR[m_dwCounterListBufferSize];
+ }
+
+ dlgConfig.bIncludeInstanceIndex = 0;
+ dlgConfig.bSingleCounterPerAdd = 0;
+ dlgConfig.bSingleCounterPerDialog = 0;
+ dlgConfig.bLocalCountersOnly = 0;
+ dlgConfig.bWildCardInstances = 1;
+ dlgConfig.bHideDetailBox = 0;
+ dlgConfig.bInitializePath = 0;
+ dlgConfig.bDisableMachineSelection = 0;
+ dlgConfig.bReserved = 0;
+
+ dlgConfig.hWndOwner = this->m_hWnd;
+ dlgConfig.szReserved = NULL;
+
+ dlgConfig.szReturnPathBuffer = m_szCounterListBuffer;
+ dlgConfig.cchReturnPathLength = m_dwCounterListBufferSize;
+ dlgConfig.pCallBack = (CounterPathCallBack)DialogCallBack;
+ dlgConfig.dwDefaultDetailLevel = PERF_DETAIL_WIZARD;
+ dlgConfig.dwCallBackArg = (DWORD)this;
+ dlgConfig.szDialogBoxCaption = TEXT("Select Counters To Log");
+
+ cCounterList = (CListBox *)GetDlgItem(IDC_COUNTER_LIST);
+ // get count of items in the list box before calling the browser
+ lBeforeCount = cCounterList->GetCount();
+
+ PdhBrowseCounters (&dlgConfig);
+
+ // get count of items in the list box After calling the browser
+ // to see if the Apply button should enabled
+ lAfterCount = cCounterList->GetCount();
+
+ if (lAfterCount > lBeforeCount) SetModified(TRUE);
+
+ // see if the remove button should be enabled
+ GetDlgItem (IDC_REMOVE)->EnableWindow(
+ lAfterCount > 0 ? TRUE : FALSE);
+
+ delete m_szCounterListBuffer;
+ m_szCounterListBuffer = NULL;
+ m_dwCounterListBufferSize = 0;
+}
+
+void CSettingsPropPage::OnManStart()
+{
+ SetCurrentServiceState (LOG_SERV_START);
+ UpdateManualButtonsState();
+ // set focus to stop button
+ GetDlgItem(IDC_MAN_STOP)->SetFocus();
+}
+
+void CSettingsPropPage::OnManStop()
+{
+ SetCurrentServiceState (LOG_SERV_STOP);
+ UpdateManualButtonsState();
+ // set focus to start button
+ GetDlgItem(IDC_MAN_START)->SetFocus();
+}
+
+void CSettingsPropPage::OnRemove()
+{
+ CListBox *cCounterList;
+ LONG lThisItem;
+ BOOL bDone;
+ LONG lOrigCaret;
+ LONG lItemStatus;
+ LONG lItemCount;
+ BOOL bChanged = FALSE;
+ DWORD dwItemExtent;
+ CString csItemText;
+
+ cCounterList = (CListBox *)GetDlgItem(IDC_COUNTER_LIST);
+ // delete all selected items in the list box and
+ // set the cursor to the item above the original caret position
+ // or the first or last if that is out of the new range
+ lOrigCaret = cCounterList->GetCaretIndex();
+ lThisItem = 0;
+ bDone = FALSE;
+ // clear the max extent
+ m_dwMaxHorizListExtent = 0;
+ do {
+ lItemStatus = cCounterList->GetSel(lThisItem);
+ if (lItemStatus > 0) {
+ // then it's selected so delete it
+ cCounterList->DeleteString(lThisItem);
+ bChanged = TRUE;
+ } else if (lItemStatus == 0) {
+ // get the text length of this item since it will stay
+ cCounterList->GetText(lThisItem, csItemText);
+ dwItemExtent = (DWORD)((cCounterList->GetDC())->GetTextExtent(csItemText)).cx;
+ if (dwItemExtent > m_dwMaxHorizListExtent) {
+ m_dwMaxHorizListExtent = dwItemExtent;
+ }
+ // then it's not selected so go to the next one
+ lThisItem++;
+ } else {
+ // we've run out so exit
+ bDone = TRUE;
+ }
+ } while (!bDone);
+
+ // update the text extent of the list box
+ cCounterList->SetHorizontalExtent(m_dwMaxHorizListExtent);
+
+ // see how many entries are left and update the
+ // caret position and the remove button state
+ lItemCount = cCounterList->GetCount();
+ if (lItemCount > 0) {
+ // the update the caret
+ if (lOrigCaret >= lItemCount) {
+ lOrigCaret = lItemCount-1;
+ } else {
+ // caret should be within the list
+ }
+ cCounterList->SetSel(lOrigCaret);
+ cCounterList->SetCaretIndex(lOrigCaret);
+ } else {
+ // the list is empty so remove caret, selection
+ // disable the remove button and activate the
+ // add button
+ cCounterList->SetSel(-1);
+ GetDlgItem(IDC_BROWSE_COUNTERS)->SetFocus();
+ GetDlgItem(IDC_REMOVE)->EnableWindow(FALSE);
+ }
+ SetModified(bChanged);
+}
+
+void CSettingsPropPage::OnServiceAuto()
+{
+ // set service to AutoStart
+ UpdateManualButtonsState();
+ SetModified(TRUE);
+}
+
+void CSettingsPropPage::OnServiceMan()
+{
+ // set service to manual Start
+ UpdateManualButtonsState();
+ SetModified(TRUE);
+}
+
+void CSettingsPropPage::OnDeltaposIntervalSpin(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ TCHAR szStringValue[MAX_PATH];
+ DWORD dwNumValue;
+ int nChange;
+
+ NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
+
+ // get current value from edit window
+ GetDlgItemText (IDC_INTERVAL_TIME, szStringValue, MAX_PATH);
+
+ // convert to integer
+ dwNumValue = _tcstoul (szStringValue, NULL, 10);
+ // delta is opposite of arrow direction
+ nChange = -pNMUpDown->iDelta;
+
+ // apply value from spin control
+ if (nChange < 0) {
+ // make sure we haven't hit bottom already
+ // we can't allow a 0 to be "spin-ed" in
+ if (dwNumValue > 1) {
+ dwNumValue += nChange;
+ }
+ } else {
+ dwNumValue += nChange;
+ }
+
+ // update edit window
+ _ultot (dwNumValue, szStringValue, 10);
+
+ SetDlgItemText(IDC_INTERVAL_TIME, szStringValue);
+
+ SetModified(TRUE);
+
+ *pResult = 0;
+}
+
+void CSettingsPropPage::OnCancel()
+{
+
+ CPropertyPage::OnCancel();
+}
+
+void CSettingsPropPage::OnOK()
+{
+ CListBox *cCounterList;
+ CString cIntervalString;
+ CString cCounterListString;
+ CString cThisCounterName;
+ DWORD dwSampleInterval;
+ LONG lIntervalUnits;
+ DWORD dwNumCounters;
+ DWORD dwThisCounter;
+ DWORD dwBufferLength;
+ LONG lStatus;
+ LPTSTR mszCounterPathList = NULL;
+ LPTSTR szNextItemInList;
+
+ BOOL bStopped, bPaused;
+
+ cCounterList = (CListBox *)GetDlgItem(IDC_COUNTER_LIST);
+ // get service state
+ GetCurrentServiceState (&bStopped, &bPaused);
+
+ if (!bStopped) {
+ AfxMessageBox (IDS_STOP_AND_START);
+ }
+
+ // write changes to registry
+ //*********************************
+
+ // update service start mode if necessary
+ SyncServiceStartWithButtons();
+
+ // sample interval
+ // read value
+ GetDlgItemText (IDC_INTERVAL_TIME, cIntervalString);
+ dwSampleInterval = _tcstoul((LPCTSTR)cIntervalString, NULL, 10);
+
+ // read units
+ lIntervalUnits = ((CComboBox *)GetDlgItem(IDC_INTERVAL_UNITS))->GetCurSel();
+
+ // convert value to seconds based on units
+ switch (lIntervalUnits) {
+ case SIU_MINUTES:
+ dwSampleInterval *= SECONDS_IN_MINUTE;
+ break;
+
+ case SIU_HOURS:
+ dwSampleInterval *= SECONDS_IN_HOUR;
+ break;
+
+ case SIU_DAYS:
+ dwSampleInterval *= SECONDS_IN_DAY;
+ break;
+
+ case SIU_SECONDS:
+ default:
+ // already in second so leave it
+ break;
+ }
+
+ // write value to registry
+ lStatus = RegSetValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Sample Interval"),
+ 0L,
+ REG_DWORD,
+ (LPBYTE)&dwSampleInterval,
+ sizeof(DWORD));
+
+ if (lStatus != ERROR_SUCCESS) {
+ // unable to update value
+ }
+
+ //*********************************
+ // counter list
+ // retrieve items from list box
+ dwNumCounters = cCounterList->GetCount();
+ dwBufferLength = 0;
+ // determine required buffer size
+ for (dwThisCounter = 0; dwThisCounter < dwNumCounters; dwThisCounter++) {
+ dwBufferLength += cCounterList->GetTextLen (dwThisCounter) + 1;
+ }
+ // add terminating NULL char
+ dwBufferLength++;
+ // allocate string buffer and copy list box entries to MSZ
+ mszCounterPathList = new TCHAR[dwBufferLength];
+ ASSERT (mszCounterPathList != NULL);
+
+ // load listbox entries into MSZ
+ szNextItemInList = mszCounterPathList;
+ *szNextItemInList = 0;
+ for (dwThisCounter = 0; dwThisCounter < dwNumCounters; dwThisCounter++) {
+ lStatus = cCounterList->GetText(dwThisCounter, szNextItemInList);
+ lStatus /= sizeof(TCHAR);
+ szNextItemInList += lStatus;
+ *szNextItemInList++ = 0;
+ }
+ *szNextItemInList++ = 0;
+ dwBufferLength = (LPBYTE)szNextItemInList - (LPBYTE)mszCounterPathList;
+
+ // write MSZ to registry
+
+ lStatus = RegSetValueEx (
+ m_hKeyLogSettingsDefault,
+ TEXT("Counter List"),
+ 0L,
+ REG_MULTI_SZ,
+ (LPBYTE)mszCounterPathList,
+ dwBufferLength);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // unable to update value
+ }
+
+ delete mszCounterPathList;
+
+ CancelToClose();
+}
+
+BOOL CSettingsPropPage::OnQueryCancel()
+{
+ return CPropertyPage::OnQueryCancel();
+}
+
+
+void CSettingsPropPage::OnSelchangeIntervalUnits()
+{
+ SetModified(TRUE);
+}
+
+void CSettingsPropPage::OnRemoveService()
+{
+ SC_HANDLE hSC = NULL;
+ SC_HANDLE hService = NULL;
+ DWORD dwMoreBytes = 0;
+ LONG lStatus;
+
+ if (AfxMessageBox (IDS_REMOVE_SERVICE_WARNING,
+ MB_OKCANCEL | MB_DEFBUTTON2) == IDCANCEL) {
+ return;
+ }
+
+ // open SC database
+ hSC = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (hSC == NULL) {
+ lStatus = GetLastError();
+ ASSERT (lStatus != ERROR_SUCCESS);
+ }
+ // open service
+ hService = OpenService (hSC, TEXT("PerfDataLog"),
+ SERVICE_CHANGE_CONFIG | DELETE);
+
+ if (hService != NULL) {
+ // Delete the service
+ if (DeleteService (hService)) {
+ EndDialog (IDCANCEL);
+ }
+ CloseServiceHandle (hService);
+ } else {
+ lStatus = GetLastError();
+ ASSERT (lStatus != 0);
+ }
+
+ // close handles
+ if (hSC != NULL) CloseServiceHandle (hSC);
+
+ return;
+}
+
+
+
+void CSettingsPropPage::OnChangeIntervalTime()
+{
+ // TODO: Add your control notification handler code here
+ SetModified(TRUE);
+}
+
diff --git a/private/sdktools/perflog/pdlcnfig/setpage.h b/private/sdktools/perflog/pdlcnfig/setpage.h
new file mode 100644
index 000000000..a299accda
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/setpage.h
@@ -0,0 +1,75 @@
+// SetPage.h : header file
+//
+#include "resource.h" // main symbols
+#include "common.h"
+#include "pdlcnfig.h"
+/////////////////////////////////////////////////////////////////////////////
+// CSettingsPropPage dialog
+
+class CSettingsPropPage : public CPropertyPage
+{
+ DECLARE_DYNCREATE(CSettingsPropPage)
+
+// Construction
+public:
+ CSettingsPropPage();
+ ~CSettingsPropPage();
+
+// Dialog Data
+ //{{AFX_DATA(CSettingsPropPage)
+ enum { IDD = IDD_SETTINGS_PAGE };
+ DWORD m_IntervalTime;
+ CString m_SettingsFile;
+ int m_IntervalUnitsIndex;
+ //}}AFX_DATA
+
+ LPTSTR m_szCounterListBuffer;
+ DWORD m_dwCounterListBufferSize;
+
+ DWORD m_dwMaxHorizListExtent;
+
+// TEMPORARY Variables until service is completed
+ BOOL bServiceStopped;
+ BOOL bServicePaused;
+
+// Overrides
+ // ClassWizard generate virtual function overrides
+ //{{AFX_VIRTUAL(CSettingsPropPage)
+ public:
+ virtual void OnCancel();
+ virtual void OnOK();
+ virtual BOOL OnQueryCancel();
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX);
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CSettingsPropPage)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnBrowseCounters();
+ afx_msg void OnManPause();
+ afx_msg void OnManResume();
+ afx_msg void OnManStart();
+ afx_msg void OnManStop();
+ afx_msg void OnRemove();
+ afx_msg void OnServiceAuto();
+ afx_msg void OnServiceMan();
+ afx_msg void OnDeltaposIntervalSpin(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnSelchangeIntervalUnits();
+ afx_msg void OnRemoveService();
+ afx_msg void OnChangeIntervalTime();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+ LONG SyncServiceStartWithButtons(void);
+ void UpdateManualButtonsState(void);
+
+ HKEY m_hKeyLogService;
+ HKEY m_hKeyLogSettingsDefault;
+ LONG GetCurrentServiceState (BOOL *, BOOL *);
+ LONG SetCurrentServiceState (DWORD);
+};
+
+
diff --git a/private/sdktools/perflog/pdlcnfig/sources b/private/sdktools/perflog/pdlcnfig/sources
new file mode 100644
index 000000000..5332d1cb8
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/sources
@@ -0,0 +1,62 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+!ifndef U_UNICODE
+U_UNICODE=0
+!endif
+
+USER_C_FLAGS=-YX"stdafx.h" -MD
+
+!if $(U_UNICODE)
+C_DEFINES=-DUNICODE=1 -D_UNICODE=1
+!else
+C_DEFINES=-D_MBCS=1
+!endif
+
+GPSIZE=32
+
+USE_MFC=1
+
+INCLUDES=.
+
+TARGETNAME=pdlcnfig
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+NTTARGETFILE0=pdlcnfig.hlp pdlcnfig.cnt
+
+SOURCES=stdafx.cpp \
+ outpage.cpp \
+ pdlcnfig.cpp \
+ setpage.cpp \
+ pdlcnfig.rc
+
+UMTYPE=windows
+UMLIBS=obj\*\pdlcnfig.res \
+ obj\*\pdlcnfig.lib \
+ $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \
+ $(BASEDIR)\public\sdk\lib\*\pdh.lib
+
+UMAPPL=pdlcnfig
+ \ No newline at end of file
diff --git a/private/sdktools/perflog/pdlcnfig/stdafx.cpp b/private/sdktools/perflog/pdlcnfig/stdafx.cpp
new file mode 100644
index 000000000..acab582e7
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/stdafx.cpp
@@ -0,0 +1,7 @@
+// stdafx.cpp : source file that includes just the standard includes
+// pdlcnfig.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+
diff --git a/private/sdktools/perflog/pdlcnfig/stdafx.h b/private/sdktools/perflog/pdlcnfig/stdafx.h
new file mode 100644
index 000000000..44bd1eef3
--- /dev/null
+++ b/private/sdktools/perflog/pdlcnfig/stdafx.h
@@ -0,0 +1,15 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+//#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows 95 Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+#include <stdlib.h>
+#include <winperf.h> // windows NT Performance definitions
+#include <pdh.h> // PDH function definitions
diff --git a/private/sdktools/perflog/pdlsvc/logthred.c b/private/sdktools/perflog/pdlsvc/logthred.c
new file mode 100644
index 000000000..fbd413db5
--- /dev/null
+++ b/private/sdktools/perflog/pdlsvc/logthred.c
@@ -0,0 +1,644 @@
+/*++
+
+Copyright (c) 1996 Microsoft Corporation
+
+Module Name:
+
+ LogThred.c
+
+Abstract:
+
+ module containing logging thread functions
+
+Author:
+
+ Bob Watson (a-robw) 10 Apr 96
+
+Revision History:
+
+--*/
+#ifndef UNICODE
+#define UNICODE 1
+#endif
+#ifndef _UNICODE
+#define _UNICODE 1
+#endif
+//
+// Windows Include files
+//
+#include <windows.h>
+#include <stdio.h>
+#include <tchar.h>
+#include <pdh.h>
+#include <pdhmsg.h>
+#include "pdlsvc.h"
+#include "logutils.h"
+#include "pdlmsg.h"
+
+DWORD
+GetSamplesInRenameInterval(
+ IN DWORD dwSampleInterval, // in seconds
+ IN DWORD dwRenameIntervalCount, // in units
+ IN DWORD dwRenameIntervalUnits) // for "count" arg
+{
+ DWORD dwRenameIntervalSeconds;
+ // convert rename interval to seconds
+
+ dwRenameIntervalSeconds = dwRenameIntervalCount;
+
+ switch (dwRenameIntervalUnits) {
+ case OPD_RENAME_HOURS:
+ dwRenameIntervalSeconds *= SECONDS_IN_HOUR;
+ break;
+
+ case OPD_RENAME_DAYS:
+ default:
+ dwRenameIntervalSeconds *= SECONDS_IN_DAY;
+ break;
+
+ case OPD_RENAME_MONTHS:
+ dwRenameIntervalSeconds *= SECONDS_IN_DAY * 30;
+ break;
+
+ case OPD_RENAME_KBYTES:
+ case OPD_RENAME_MBYTES:
+ // these don't use a rename counter
+ return (DWORD)0;
+ break;
+ }
+ dwRenameIntervalSeconds /= dwSampleInterval;
+
+ return (dwRenameIntervalSeconds);
+}
+
+LONG
+BuildCurrentLogFileName (
+ IN LPCTSTR szBaseFileName,
+ IN LPCTSTR szDefaultDir,
+ IN LPTSTR szOutFileBuffer,
+ IN LPDWORD lpdwSerialNumber,
+ IN DWORD dwDateFormat,
+ IN DWORD dwLogFormat
+)
+// presumes OutFileBuffer is large enough (i.e. >= MAX_PATH)
+{
+ SYSTEMTIME st;
+ BOOL bUseCurrentDir = FALSE;
+ TCHAR szAuto[MAX_PATH];
+ LPTSTR szExt;
+
+ if (szDefaultDir != NULL) {
+ if (*szDefaultDir == 0) {
+ bUseCurrentDir = TRUE;
+ }
+ } else {
+ bUseCurrentDir = TRUE;
+ }
+
+ if (bUseCurrentDir) {
+ GetCurrentDirectory (MAX_PATH, szOutFileBuffer);
+ } else {
+ lstrcpy (szOutFileBuffer, szDefaultDir);
+ }
+
+ // add a backslash to the path name if it doesn't have one already
+
+ if (szOutFileBuffer[lstrlen(szOutFileBuffer)-1] != TEXT('\\')) {
+ lstrcat (szOutFileBuffer, TEXT("\\"));
+ }
+
+ // add the base filename
+
+ lstrcat (szOutFileBuffer, szBaseFileName);
+
+ // add the auto name part
+
+ // get date/time/serial integer format
+ GetLocalTime(&st);
+
+ switch (dwDateFormat) {
+ case OPD_NAME_NNNNNN:
+ _stprintf (szAuto, TEXT("_%6.6d"), *lpdwSerialNumber);
+ (*lpdwSerialNumber)++; // increment
+ if (*lpdwSerialNumber >= 1000000) {
+ // roll over to 0
+ *lpdwSerialNumber = 0;
+ }
+ break;
+
+ case OPD_NAME_YYDDD:
+ _stprintf (szAuto, TEXT("_%2.2d%2.2d"),
+ st.wYear % 100, st.wMonth);
+ break;
+
+ case OPD_NAME_YYMM:
+ _stprintf (szAuto, TEXT("_%2.2d%2.2d"),
+ st.wYear % 100, st.wMonth);
+ break;
+
+ case OPD_NAME_YYMMDDHH:
+ _stprintf (szAuto, TEXT("_%2.2d%2.2d%2.2d%2.2d"),
+ (st.wYear % 100), st.wMonth, st.wDay, st.wHour);
+ break;
+
+ case OPD_NAME_MMDDHH:
+ _stprintf (szAuto, TEXT("_%2.2d%2.2d%2.2d"),
+ st.wMonth, st.wDay, st.wHour);
+ break;
+
+ case OPD_NAME_YYMMDD:
+ default:
+ _stprintf (szAuto, TEXT("_%2.2d%2.2d%2.2d"),
+ st.wMonth, st.wDay, st.wHour);
+ break;
+ }
+
+ lstrcat (szOutFileBuffer, szAuto);
+
+ // get file type
+ switch (dwLogFormat) {
+ case OPD_TSV_FILE:
+ szExt = TEXT(".tsv");
+ break;
+
+ case OPD_BIN_FILE:
+ szExt = TEXT(".blg");
+ break;
+
+ case OPD_CSV_FILE:
+ default:
+ szExt = TEXT(".csv");
+ break;
+ }
+
+ lstrcat (szOutFileBuffer, szExt);
+
+ return ERROR_SUCCESS;
+}
+
+BOOL
+LoadDataFromRegistry (
+ IN LPLOG_THREAD_DATA pArg,
+ IN LPTSTR szDefaultDir,
+ IN LPTSTR szBaseName,
+ IN LPTSTR szCurrentLogFile
+)
+{
+ LONG lStatus;
+ DWORD dwType;
+ DWORD dwSize;
+ DWORD dwData;
+ LPTSTR szStringArray[2];
+
+ // get size of buffer required by counter list,
+ // then allocate the buffer and retrieve the counter list
+
+ dwType = 0;
+ dwData = 0;
+ dwSize = 0;
+ lStatus = RegQueryValueEx (
+ pArg->hKeyQuery,
+ TEXT("Counter List"),
+ NULL,
+ &dwType,
+ (LPBYTE)NULL,
+ &dwSize);
+
+ pArg->mszCounterList = (LPTSTR)G_ALLOC(dwSize);
+
+ if (pArg->mszCounterList != NULL) {
+ dwType = 0;
+ lStatus = RegQueryValueEx (
+ pArg->hKeyQuery,
+ TEXT("Counter List"),
+ NULL,
+ &dwType,
+ (LPBYTE)pArg->mszCounterList,
+ &dwSize);
+
+ if ((lStatus != ERROR_SUCCESS) || (dwSize == 0)) {
+ // no counter list retrieved so there's not much
+ // point in continuing
+ szStringArray[0] = pArg->szQueryName;
+ ReportEvent (hEventLog,
+ EVENTLOG_ERROR_TYPE,
+ 0,
+ PERFLOG_UNABLE_READ_COUNTER_LIST,
+ NULL,
+ 1,
+ sizeof(DWORD),
+ szStringArray,
+ (LPVOID)&lStatus);
+ return FALSE;
+ }
+ } else {
+ szStringArray[0] = pArg->szQueryName;
+ ReportEvent (hEventLog,
+ EVENTLOG_ERROR_TYPE,
+ 0,
+ PERFLOG_UNABLE_ALLOC_COUNTER_LIST,
+ NULL,
+ 1,
+ sizeof(DWORD),
+ szStringArray,
+ (LPVOID)&lStatus);
+ return FALSE;
+ }
+
+ dwType = 0;
+ dwData = 0;
+ dwSize = sizeof(DWORD);
+ lStatus = RegQueryValueEx (
+ pArg->hKeyQuery,
+ TEXT("Auto Name Interval"),
+ NULL,
+ &dwType,
+ (LPBYTE)&dwData,
+ &dwSize);
+ if (lStatus != ERROR_SUCCESS) {
+ dwData = 0; // default is no autonaming
+ } else if (dwType != REG_DWORD) {
+ dwData = 0; // default is no autonaming
+ } // else assume success
+
+ pArg->dwRenameIntervalCount = dwData;
+
+ dwType = 0;
+ dwData = 0;
+ dwSize = sizeof(DWORD);
+ lStatus = RegQueryValueEx (
+ pArg->hKeyQuery,
+ TEXT("Auto Rename Units"),
+ NULL,
+ &dwType,
+ (LPBYTE)&dwData,
+ &dwSize);
+ if (lStatus != ERROR_SUCCESS) {
+ dwData = OPD_RENAME_DAYS; // default is days
+ } else if (dwType != REG_DWORD) {
+ dwData = OPD_RENAME_DAYS; // default is days
+ } // else assume success
+
+ pArg->dwRenameIntervalUnits = dwData;
+
+ dwType = 0;
+ dwData = 0;
+ dwSize = sizeof(DWORD);
+ lStatus = RegQueryValueEx (
+ pArg->hKeyQuery,
+ TEXT("Log File Auto Format"),
+ NULL,
+ &dwType,
+ (LPBYTE)&dwData,
+ &dwSize);
+ if (lStatus != ERROR_SUCCESS) {
+ dwData = OPD_NAME_NNNNNN; // default is a serial number
+ } else if (dwType != REG_DWORD) {
+ dwData = OPD_NAME_NNNNNN; // default is a serial number
+ } // else assume success
+
+ pArg->dwAutoNameFormat = dwData;
+
+ dwType = 0;
+ dwData = 0;
+ dwSize = sizeof(DWORD);
+ lStatus = RegQueryValueEx (
+ pArg->hKeyQuery,
+ TEXT("Log File Type"),
+ NULL,
+ &dwType,
+ (LPBYTE)&dwData,
+ &dwSize);
+ if (lStatus != ERROR_SUCCESS) {
+ dwData = OPD_CSV_FILE; // default is a CSV file
+ } else if (dwType != REG_DWORD) {
+ dwData = OPD_CSV_FILE; // default is a CSV file
+ } // else assume success
+
+ pArg->dwLogType = dwData;
+
+ dwType = 0;
+ dwData = 0;
+ dwSize = sizeof(DWORD);
+ lStatus = RegQueryValueEx (
+ pArg->hKeyQuery,
+ TEXT("Sample Interval"),
+ NULL,
+ &dwType,
+ (LPBYTE)&dwData,
+ &dwSize);
+ if (lStatus != ERROR_SUCCESS) {
+ dwData = SECONDS_IN_MINUTE; // default is 1 Minute samples
+ } else if (dwType != REG_DWORD) {
+ dwData = SECONDS_IN_MINUTE; // default is 1 Minute samples
+ } // else assume success
+
+ pArg->dwTimeInterval = dwData;
+
+ // get filename or components if auto name
+
+ if (pArg->dwRenameIntervalCount > 0) {
+ // this is an autoname file so get components
+ dwType = 0;
+ *szDefaultDir = 0;
+ dwSize = MAX_PATH * sizeof(TCHAR);
+ lStatus = RegQueryValueEx (
+ pArg->hKeyQuery,
+ TEXT("Log Default Directory"),
+ NULL,
+ &dwType,
+ (LPBYTE)&szDefaultDir[0],
+ &dwSize);
+ if (lStatus != ERROR_SUCCESS) {
+ *szDefaultDir = 0;
+ } // else assume success
+
+ dwType = 0;
+ *szBaseName = 0;
+ dwSize = MAX_PATH * sizeof(TCHAR);
+ lStatus = RegQueryValueEx (
+ pArg->hKeyQuery,
+ TEXT("Base Filename"),
+ NULL,
+ &dwType,
+ (LPBYTE)&szBaseName[0],
+ &dwSize);
+ if (lStatus != ERROR_SUCCESS) {
+ // apply default
+ lstrcpy (szBaseName, TEXT("perfdata"));
+ } // else assume success
+ } else {
+ // this is a manual name file so read name
+ dwType = 0;
+ *szCurrentLogFile = 0;
+ dwSize = MAX_PATH * sizeof(TCHAR);
+ lStatus = RegQueryValueEx (
+ pArg->hKeyQuery,
+ TEXT("Log Filename"),
+ NULL,
+ &dwType,
+ (LPBYTE)&szCurrentLogFile[0],
+ &dwSize);
+ if (lStatus != ERROR_SUCCESS) {
+ // apply default
+ lstrcpy (szCurrentLogFile, TEXT("c:\\perfdata.log"));
+ } // else assume success
+ }
+
+ dwType = 0;
+ dwData = 0;
+ dwSize = sizeof(DWORD);
+ lStatus = RegQueryValueEx (
+ pArg->hKeyQuery,
+ TEXT("Log File Serial Number"),
+ NULL,
+ &dwType,
+ (LPBYTE)&dwData,
+ &dwSize);
+ if (lStatus != ERROR_SUCCESS) {
+ dwData = 1; // default is to start at 1
+ } else if (dwType != REG_DWORD) {
+ dwData = 1; // default is to start at 1
+ } // else assume success
+
+ pArg->dwCurrentSerialNumber = dwData;
+ return TRUE;
+}
+
+BOOL
+LoggingProc (
+ IN LPLOG_THREAD_DATA pArg
+)
+{
+ HQUERY hQuery;
+ HCOUNTER hThisCounter;
+ DWORD dwDelay;
+ DWORD dwSampleInterval, dwSampleTime;
+ PDH_STATUS pdhStatus;
+ DWORD dwNumCounters;
+ LONG lStatus;
+ TCHAR szDefaultDir[MAX_PATH];
+ TCHAR szBaseName[MAX_PATH];
+
+ LPTSTR szThisPath;
+ DWORD dwLogType = OPD_CSV_FILE;
+ BOOL bRun = FALSE;
+ DWORD dwSamplesUntilNewFile;
+ TCHAR szCurrentLogFile[MAX_PATH];
+ LONG lWaitStatus;
+ LPTSTR szStringArray[4];
+ DWORD dwFileSizeLimit;
+ LONGLONG llFileSizeLimit;
+ LONGLONG llFileSize;
+ PLOG_COUNTER_INFO pCtrInfo;
+
+ // read registry values
+
+ if (!LoadDataFromRegistry (pArg, szDefaultDir, szBaseName, szCurrentLogFile)) {
+ // unable to initialize the query from the registry
+ return FALSE;
+ }
+
+ // convert to milliseconds for use in timeouts
+ dwSampleInterval = pArg->dwTimeInterval * 1000L;
+
+ // open query and add counters from info file
+
+ pdhStatus = PdhOpenQuery (NULL, 0, &hQuery); // from current activity
+ if (pdhStatus == ERROR_SUCCESS) {
+ dwNumCounters = 0;
+ for (szThisPath = pArg->mszCounterList;
+ *szThisPath != 0;
+ szThisPath += lstrlen(szThisPath) + 1) {
+ pdhStatus = PdhAddCounter (hQuery,
+ (LPTSTR)szThisPath, dwNumCounters++, &hThisCounter);
+
+ if (pdhStatus == ERROR_SUCCESS) {
+ // then add this handle to the list
+ pCtrInfo = G_ALLOC (sizeof (LOG_COUNTER_INFO));
+ if (pCtrInfo != NULL) {
+ // insert at front of list since the order isn't
+ // important and this is simpler than walking the
+ // list each time.
+ pCtrInfo->hCounter = hThisCounter;
+ pCtrInfo->next = pFirstCounter;
+ pFirstCounter = pCtrInfo;
+ }
+ }
+ }
+
+ // to make sure we get to log the data
+ SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
+
+ bRun = TRUE;
+ while (bRun) {
+ // Get the current Log filename
+ if (pArg->dwRenameIntervalCount != 0) {
+ // then this is an autonamed file
+ // so make current name
+ BuildCurrentLogFileName (
+ szBaseName,
+ szDefaultDir,
+ szCurrentLogFile,
+ &pArg->dwCurrentSerialNumber,
+ pArg->dwAutoNameFormat,
+ pArg->dwLogType);
+ // reset loop counter
+ switch (pArg->dwRenameIntervalUnits) {
+ case OPD_RENAME_KBYTES:
+ dwFileSizeLimit = pArg->dwRenameIntervalCount * 1024;
+ dwSamplesUntilNewFile = 0;
+ break;
+
+ case OPD_RENAME_MBYTES:
+ dwFileSizeLimit = pArg->dwRenameIntervalCount * 1024 * 1024;
+ dwSamplesUntilNewFile = 0;
+ break;
+
+ case OPD_RENAME_HOURS:
+ case OPD_RENAME_DAYS:
+ case OPD_RENAME_MONTHS:
+ default:
+ dwSamplesUntilNewFile = GetSamplesInRenameInterval(
+ pArg->dwTimeInterval,
+ pArg->dwRenameIntervalCount,
+ pArg->dwRenameIntervalUnits);
+ dwFileSizeLimit = 0;
+ break;
+ }
+ } else {
+ // filename is left as read from the registry
+ dwSamplesUntilNewFile = 0;
+ dwFileSizeLimit = 0;
+ }
+ llFileSizeLimit = dwFileSizeLimit;
+ // open log file using this query
+ dwLogType = pArg->dwLogType;
+ pdhStatus = OpenLogW (
+ szCurrentLogFile,
+ LOG_WRITE_ACCESS | LOG_CREATE_ALWAYS,
+ &dwLogType,
+ hQuery,
+ 0);
+
+ if (pdhStatus == ERROR_SUCCESS) {
+ szStringArray[0] = pArg->szQueryName;
+ szStringArray[1] = szCurrentLogFile;
+ ReportEvent (hEventLog,
+ EVENTLOG_INFORMATION_TYPE,
+ 0,
+ PERFLOG_LOGGING_QUERY,
+ NULL,
+ 2,
+ 0,
+ szStringArray,
+ NULL);
+ // start sampling immediately
+ dwDelay = 0;
+ while ((lWaitStatus = WaitForSingleObject (pArg->hExitEvent, dwDelay)) == WAIT_TIMEOUT) {
+ // the event flag will be set when the sampling should exit. if
+ // the wait times out, then that means it's time to collect and
+ // log another sample of data.
+ // the argument received the time it took to take the
+ // sample so the delay can be adjusted accordingly
+ dwSampleTime = 0;
+ pdhStatus = UpdateLog (&dwSampleTime);
+
+ if (pdhStatus == ERROR_SUCCESS) {
+ // see if it's time to rename the file
+ if (dwSamplesUntilNewFile) {
+ if (!--dwSamplesUntilNewFile) break;
+ } else if (llFileSizeLimit) {
+ // see if the file is too big
+ pdhStatus = GetLogFileSize (&llFileSize);
+ if (pdhStatus == ERROR_SUCCESS) {
+ if (llFileSizeLimit <= llFileSize) break;
+ }
+ }
+ // compute new timeout value
+ if (dwSampleTime < dwSampleInterval) {
+ dwDelay = dwSampleInterval - dwSampleTime;
+ } else {
+ dwDelay = 0;
+ }
+ } else {
+ // unable to update the log so log event and exit
+ ReportEvent (hEventLog,
+ EVENTLOG_ERROR_TYPE,
+ 0,
+ PERFLOG_UNABLE_UPDATE_LOG,
+ NULL,
+ 0,
+ sizeof(DWORD),
+ NULL,
+ (LPVOID)&pdhStatus);
+
+ bRun = FALSE;
+ break;
+ }
+
+ } // end while wait keeps timing out
+ if (lWaitStatus == WAIT_OBJECT_0) {
+ // then the loop was terminated by the Exit event
+ // so clear the "run" flag to exit the loop & thread
+ bRun = FALSE;
+ }
+ CloseLog (0);
+
+ } else {
+ // unable to open log file so log event log message
+ bRun = FALSE; // exit now
+ }
+ } // end while (bRun)
+ PdhCloseQuery (hQuery);
+
+ // update log serial number if necssary
+ if (pArg->dwAutoNameFormat == OPD_NAME_NNNNNN) {
+ lStatus = RegSetValueEx (
+ pArg->hKeyQuery,
+ TEXT("Log File Serial Number"),
+ 0L,
+ REG_DWORD,
+ (LPBYTE)&pArg->dwCurrentSerialNumber,
+ sizeof(DWORD));
+ }
+ } else {
+ // unable to open query so write event log message
+ }
+
+ return bRun;
+}
+
+DWORD
+LoggingThreadProc (
+ IN LPVOID lpThreadArg
+)
+{
+ LPLOG_THREAD_DATA pThreadData = (LPLOG_THREAD_DATA)lpThreadArg;
+ DWORD dwStatus = ERROR_SUCCESS;
+ BOOL bContinue = TRUE;
+
+ if (pThreadData != NULL) {
+ // read config from registry
+
+ do {
+ // read config from registry
+ // expand counter paths as necessary
+ // call Logging function
+ bContinue = LoggingProc (pThreadData);
+ // see if this thread was paused for reloading
+ // or stopped to terminate
+ if (pThreadData->bReloadNewConfig) {
+ bContinue = TRUE;
+ } // else bContinue is always returned as FALSE
+ // so that will terminate this loop
+ } while (bContinue);
+ dwStatus = ERROR_SUCCESS;
+ } else {
+ // unable to find data block so return
+ dwStatus = ERROR_INVALID_PARAMETER;
+ }
+
+ return dwStatus;
+}
+
diff --git a/private/sdktools/perflog/pdlsvc/logutils.c b/private/sdktools/perflog/pdlsvc/logutils.c
new file mode 100644
index 000000000..420e4dcbf
--- /dev/null
+++ b/private/sdktools/perflog/pdlsvc/logutils.c
@@ -0,0 +1,914 @@
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pdh.h>
+#include <pdhmsg.h>
+#include <common.h>
+#include "pdlsvc.h"
+#include "logutils.h"
+
+
+// local definitions
+typedef struct _LOG_INFO {
+ DWORD dwLength; // the size of this structure
+ LPWSTR szLogFileName; // full file name for this log file
+ HANDLE hLogFileHandle; // handle to open log file
+
+ HANDLE hMappedLogFile; // handle for memory mapped files
+ LPVOID lpMappedFileBase; // starting address for mapped log file
+ FILE *StreamFile; // stream pointer for text files
+ DWORD dwLastRecordRead; // index of last record read from the file
+
+ LPSTR szLastRecordRead; // pointer to buffer containing the last record
+ LPWSTR szCatFileName; // catalog file name
+ HANDLE hCatFileHandle; // handle to the open catalog file
+ HQUERY hQuery; // query handle associated with the log
+
+ DWORD dwMaxRecords; // max size of a circular log file
+ DWORD dwLogFormat; // log type and access flags
+} LOG_INFO, *PLOG_INFO;
+
+// note that when the text format headers are written
+// they will be prefixed with a double quote character
+// the binary header will not. That's why there's a space
+// in the binary string so the offset in the file will be
+// the same.
+
+#define VALUE_BUFFER_SIZE 32
+//
+// local static variables
+//
+static LOG_INFO LogEntry = {0,NULL,NULL,
+ NULL,NULL,NULL,0,
+ NULL,NULL,NULL,NULL,
+ 0,0};
+
+#define TAB_DELIMITER '\t'
+#define COMMA_DELIMITER ','
+#define DOUBLE_QUOTE '\"'
+#define VALUE_BUFFER_SIZE 32
+
+const CHAR szFmtTimeStamp[] = {"\"%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d.%3.3d\""};
+const CHAR szFmtRealValue[] = {"%c\"%.20g\""};
+const CHAR szRecordTerminator[] = {"\r\n"};
+const DWORD dwRecordTerminatorLength = 2;
+const CHAR szTimeStampLabel[] = {" Sample Time\""};
+const DWORD dwTimeStampLabelLength = 13;
+
+#define TEXTLOG_TYPE_ID_RECORD 1
+#define TEXTLOG_HEADER_RECORD 1
+#define TEXTLOG_FIRST_DATA_RECORD 2
+
+#define TIME_FIELD_COUNT 7
+#define TIME_FIELD_BUFF_SIZE 24
+DWORD dwTimeFieldOffsetList[TIME_FIELD_COUNT] = {2, 5, 10, 13, 16, 19, 23};
+
+BOOL
+GetLocalFileTime (
+ SYSTEMTIME *pST,
+ LONGLONG *pFileTime
+)
+{
+ BOOL bResult;
+ GetLocalTime (pST);
+ if (pFileTime != NULL) {
+ bResult = SystemTimeToFileTime (pST, (LPFILETIME)pFileTime);
+ } else {
+ bResult = TRUE;
+ }
+ return bResult;
+}
+
+static
+BOOL
+DateStringToFileTimeA (
+ IN LPSTR szDateTimeString,
+ IN LPFILETIME pFileTime
+)
+{
+ CHAR mszTimeFields[TIME_FIELD_BUFF_SIZE];
+ DWORD dwThisField;
+ LONG lValue;
+ SYSTEMTIME st;
+
+ // make string into msz
+ lstrcpynA (mszTimeFields, szDateTimeString, TIME_FIELD_BUFF_SIZE);
+ for (dwThisField = 0; dwThisField < TIME_FIELD_COUNT; dwThisField++) {
+ mszTimeFields[dwTimeFieldOffsetList[dwThisField]] = 0;
+ }
+
+ // read string into system time structure
+ dwThisField = 0;
+ st.wDayOfWeek = 0;
+ lValue = atol(&mszTimeFields[0]);
+ st.wMonth = LOWORD(lValue);
+ lValue = atol(&mszTimeFields[dwTimeFieldOffsetList[dwThisField++]+1]);
+ st.wDay = LOWORD(lValue);
+ lValue = atol(&mszTimeFields[dwTimeFieldOffsetList[dwThisField++]+1]);
+ st.wYear = LOWORD(lValue);
+ lValue = atol(&mszTimeFields[dwTimeFieldOffsetList[dwThisField++]+1]);
+ st.wHour = LOWORD(lValue);
+ lValue = atol(&mszTimeFields[dwTimeFieldOffsetList[dwThisField++]+1]);
+ st.wMinute = LOWORD(lValue);
+ lValue = atol(&mszTimeFields[dwTimeFieldOffsetList[dwThisField++]+1]);
+ st.wSecond = LOWORD(lValue);
+ lValue = atol(&mszTimeFields[dwTimeFieldOffsetList[dwThisField++]+1]);
+ st.wMilliseconds = LOWORD(lValue);
+
+ return SystemTimeToFileTime (&st, pFileTime);
+}
+
+#define GSFDL_REMOVE_QUOTES 0x00000001
+static
+DWORD
+GetStringFromDelimitedListA (
+ IN LPSTR szInputString,
+ IN DWORD dwItemIndex,
+ IN CHAR cDelimiter,
+ IN DWORD dwFlags,
+ IN LPSTR szOutputString,
+ IN DWORD cchBufferLength
+)
+{
+ DWORD dwCurrentIndex = 0;
+ LPSTR szCurrentItem;
+ LPSTR szSrcPtr, szDestPtr;
+ DWORD dwReturn = 0;
+
+ // go to desired entry in string, 0 = first entry
+ szCurrentItem = szInputString;
+
+ while (dwCurrentIndex < dwItemIndex) {
+ // goto next delimiter or terminator
+ while (*szCurrentItem++ != cDelimiter) {
+ if (*szCurrentItem == 0) break;
+ }
+ dwCurrentIndex++;
+ }
+ if (*szCurrentItem != 0) {
+ // then copy to the user's buffer, as long as it fits
+ szSrcPtr = szCurrentItem;
+ szDestPtr = szOutputString;
+ dwReturn = 0;
+ while (((*szSrcPtr != cDelimiter) && (*szSrcPtr != 0)) &&
+ (dwReturn < cchBufferLength)) {
+ if (dwFlags & GSFDL_REMOVE_QUOTES) {
+ if (*szSrcPtr == '\"') {
+ // skip the quote
+ szSrcPtr++;
+ continue;
+ }
+ }
+ *szDestPtr++ = *szSrcPtr++; // copy character
+ dwReturn++; // increment length
+ }
+ if (dwReturn > 0) {
+ *szDestPtr = 0; // add terminator char
+ }
+ }
+ return dwReturn;
+}
+
+static
+DWORD
+AddUniqueStringToMultiSz (
+ IN LPVOID mszDest,
+ IN LPSTR szSource,
+ IN BOOL bUnicodeDest
+)
+/*++
+
+Routine Description:
+
+ searches the Multi-SZ list, mszDest for szSource and appends it
+ to mszDest if it wasn't found
+
+Arguments:
+
+ OUT LPVOID mszDest Multi-SZ list to get new string
+ IN LPSTR szSource string to add if it's not already in list
+
+ReturnValue:
+
+ The new length of the destination string including both
+ trailing NULL characters if the string was added, or 0 if the
+ string is already in the list.
+
+--*/
+{
+ LPVOID szDestElem;
+ DWORD dwReturnLength;
+ LPWSTR wszSource = NULL;
+ DWORD dwLength;
+
+ // check arguments
+
+ if ((mszDest == NULL) || (szSource == NULL)) return 0; // invalid buffers
+ if (*szSource == '\0') return 0; // no source string to add
+
+ // if unicode list, make a unicode copy of the string to compare
+ // and ultimately copy if it's not already in the list
+
+ if (bUnicodeDest) {
+ dwLength = lstrlenA(szSource) + 1;
+ wszSource = G_ALLOC (dwLength * sizeof(WCHAR));
+ if (wszSource != NULL) {
+ dwReturnLength = mbstowcs (wszSource, szSource, dwLength);
+ } else {
+ // unable to allocate memory for the temp string
+ dwReturnLength = 0;
+ }
+ } else {
+ // just use the ANSI version of the source file name
+ dwReturnLength = 1;
+ }
+
+ if (dwReturnLength > 0) {
+ // go to end of dest string
+ //
+ for (szDestElem = mszDest;
+ (bUnicodeDest ? (*(LPWSTR)szDestElem != 0) :
+ (*(LPSTR)szDestElem != 0));
+ ) {
+ if (bUnicodeDest) {
+ // bail out if string already in lsit
+ if (lstrcmpiW((LPCWSTR)szDestElem, wszSource) == 0) {
+ return 0;
+ } else {
+ // goto the next item
+ szDestElem = (LPVOID)((LPWSTR)szDestElem +
+ (lstrlenW((LPCWSTR)szDestElem)+1));
+ }
+ } else {
+ // bail out if string already in lsit
+ if (lstrcmpiA((LPSTR)szDestElem, szSource) == 0) {
+ return 0;
+ } else {
+ // goto the next item
+ szDestElem = (LPVOID)((LPSTR)szDestElem +
+ (lstrlenA((LPCSTR)szDestElem)+1));
+ }
+ }
+ }
+
+ // if here, then add string
+ // szDestElem is at end of list
+
+ if (bUnicodeDest) {
+ lstrcpyW ((LPWSTR)szDestElem, wszSource);
+ szDestElem = (LPVOID)((LPWSTR)szDestElem + lstrlenW(wszSource) + 1);
+ *((LPWSTR)szDestElem)++ = L'\0';
+ dwReturnLength = (DWORD)((LPWSTR)szDestElem - (LPWSTR)mszDest);
+ } else {
+ lstrcpyA ((LPSTR)szDestElem, szSource);
+ szDestElem = (LPVOID)((LPSTR)szDestElem + lstrlenA(szDestElem) + 1);
+ *((LPSTR)szDestElem)++ = '\0'; // add second NULL
+ dwReturnLength = (DWORD)((LPSTR)szDestElem - (LPSTR)mszDest);
+ }
+ }
+
+ return dwReturnLength;
+}
+
+PDH_FUNCTION
+OpenOutputTextLog (
+ IN PLOG_INFO pLog
+)
+{
+ LONG pdhStatus;
+
+ pLog->StreamFile = (FILE *)-1;
+ pdhStatus = ERROR_SUCCESS;
+
+ return pdhStatus;
+}
+
+PDH_FUNCTION
+CloseTextLog (
+ IN PLOG_INFO pLog
+)
+{
+ LONG pdhStatus;
+
+ if (pLog->StreamFile != (FILE *)-1) {
+ fclose (pLog->StreamFile);
+ }
+ pdhStatus = ERROR_SUCCESS;
+ return pdhStatus;
+}
+
+PDH_FUNCTION
+WriteTextLogHeader (
+ IN PLOG_INFO pLog
+)
+{
+ LONG pdhStatus = ERROR_SUCCESS;
+ PLOG_COUNTER_INFO pThisCounter;
+ CHAR cDelim;
+ CHAR szLeadDelim[4];
+ DWORD dwLeadSize;
+ CHAR szTrailDelim[4];
+ DWORD dwTrailSize;
+ DWORD dwBytesWritten;
+ PPDH_COUNTER_INFO_A pCtrInfo;
+ DWORD dwCtrInfoSize;
+ BOOL bResult;
+
+ pCtrInfo = G_ALLOC (8192);
+
+ if (pCtrInfo == NULL) {
+ return PDH_MEMORY_ALLOCATION_FAILURE;
+ }
+
+ cDelim = (LOWORD(pLog->dwLogFormat) == OPD_CSV_FILE) ? COMMA_DELIMITER :
+ TAB_DELIMITER;
+
+ szLeadDelim[0] = cDelim;
+ szLeadDelim[1] = DOUBLE_QUOTE;
+ szLeadDelim[2] = 0;
+ szLeadDelim[3] = 0;
+ dwLeadSize = 2;
+
+ szTrailDelim[0] = DOUBLE_QUOTE;
+ szTrailDelim[1] = 0;
+ szTrailDelim[2] = 0;
+ szTrailDelim[3] = 0;
+ dwTrailSize = 1;
+
+
+ // write the logfile header record
+ bResult = WriteFile (pLog->hLogFileHandle,
+ (LPCVOID)&szTrailDelim[0],
+ 1,
+ &dwBytesWritten,
+ NULL);
+
+ if (!bResult) {
+ pdhStatus = GetLastError();
+ }
+
+ if (pdhStatus == ERROR_SUCCESS) {
+ // write the time stamp title
+ bResult = WriteFile (pLog->hLogFileHandle,
+ (LPCVOID)szTimeStampLabel,
+ dwTimeStampLabelLength,
+ &dwBytesWritten,
+ NULL);
+
+ if (!bResult) {
+ pdhStatus = GetLastError();
+ }
+ }
+
+ if (pdhStatus == ERROR_SUCCESS) {
+ // check each counter in the list of counters for this query and
+ // write them to the file
+
+ // output the path names
+ pThisCounter = pFirstCounter;
+
+ if (pThisCounter != NULL) {
+ do {
+ // write the leading delimiter
+ bResult = WriteFile (pLog->hLogFileHandle,
+ (LPCVOID)szLeadDelim,
+ dwLeadSize,
+ &dwBytesWritten,
+ NULL);
+
+ if (!bResult) {
+ pdhStatus = GetLastError();
+ break; // out of the Do Loop
+ }
+
+ // get the counter path information from the counter
+ dwCtrInfoSize = 8192;
+ pdhStatus = PdhGetCounterInfoA (
+ pThisCounter->hCounter,
+ FALSE,
+ &dwCtrInfoSize,
+ pCtrInfo);
+
+ if (pdhStatus == ERROR_SUCCESS) {
+ // write the counter name
+ bResult = WriteFile (pLog->hLogFileHandle,
+ (LPCVOID)pCtrInfo->szFullPath,
+ lstrlen(pCtrInfo->szFullPath),
+ &dwBytesWritten,
+ NULL);
+
+ if (!bResult) {
+ pdhStatus = GetLastError();
+ break; // out of the Do Loop
+ }
+ } else {
+ // unable to get counter information so bail here
+ break;
+ }
+
+ // write the trailing delimiter
+ bResult = WriteFile (pLog->hLogFileHandle,
+ (LPCVOID)szTrailDelim,
+ dwTrailSize,
+ &dwBytesWritten,
+ NULL);
+
+
+ if (!bResult) {
+ pdhStatus = GetLastError();
+ break; // out of the Do Loop
+ }
+
+ pThisCounter = pThisCounter->next;
+ } while (pThisCounter != NULL);
+ }
+ }
+
+ if (pdhStatus == ERROR_SUCCESS) {
+ // write the record terminator
+ bResult = WriteFile (pLog->hLogFileHandle,
+ (LPCVOID)szRecordTerminator,
+ dwRecordTerminatorLength,
+ &dwBytesWritten,
+ NULL);
+ if (!bResult) {
+ pdhStatus = GetLastError();
+ }
+ }
+
+ G_FREE (pCtrInfo);
+
+ return pdhStatus;
+}
+
+PDH_FUNCTION
+WriteTextLogRecord (
+ IN PLOG_INFO pLog,
+ IN SYSTEMTIME *stTimeStamp
+)
+{
+ LONG pdhStatus = ERROR_SUCCESS;
+ PLOG_COUNTER_INFO pThisCounter;
+ CHAR cDelim;
+ DWORD dwBytesWritten;
+ DWORD dwBufferSize;
+ CHAR szValueBuffer[VALUE_BUFFER_SIZE];
+ PDH_FMT_COUNTERVALUE pdhValue;
+ BOOL bResult;
+
+ cDelim = (LOWORD(pLog->dwLogFormat) == OPD_CSV_FILE) ? COMMA_DELIMITER :
+ TAB_DELIMITER;
+
+ // format and write the time stamp title
+
+ dwBufferSize = sprintf (szValueBuffer, szFmtTimeStamp,
+ stTimeStamp->wMonth, stTimeStamp->wDay, stTimeStamp->wYear,
+ stTimeStamp->wHour, stTimeStamp->wMinute, stTimeStamp->wSecond, stTimeStamp->wMilliseconds);
+
+ bResult = WriteFile (pLog->hLogFileHandle,
+ szValueBuffer,
+ dwBufferSize,
+ &dwBytesWritten,
+ NULL);
+
+ if (!bResult) {
+ pdhStatus = GetLastError();
+ } else {
+ // check each counter in the list of counters for this query and
+ // write them to the file
+
+ pThisCounter = pFirstCounter;
+
+ if (pThisCounter != NULL) {
+ do {
+ // get the formatted value from the counter
+
+ // compute and format current value
+ pdhStatus = PdhGetFormattedCounterValue (
+ pThisCounter->hCounter,
+ PDH_FMT_DOUBLE,
+ NULL,
+ &pdhValue);
+
+ if ((pdhStatus == ERROR_SUCCESS) &&
+ ((pdhValue.CStatus == PDH_CSTATUS_VALID_DATA) ||
+ (pdhValue.CStatus == PDH_CSTATUS_NEW_DATA))) {
+ // then this is a valid data value so print it
+ dwBufferSize = sprintf (szValueBuffer,
+ szFmtRealValue, cDelim, pdhValue.doubleValue);
+ } else {
+ // invalid data so show a blank
+ dwBufferSize = sprintf (szValueBuffer, " ");
+ // reset error value
+ pdhStatus = ERROR_SUCCESS;
+ }
+
+ // write this value to the file
+ bResult = WriteFile (pLog->hLogFileHandle,
+ szValueBuffer,
+ dwBufferSize,
+ &dwBytesWritten,
+ NULL);
+ if (!bResult) {
+ pdhStatus = GetLastError();
+ break; // out of the loop
+ }
+
+ // goto the next counter in the list
+ pThisCounter = pThisCounter->next;
+ } while (pThisCounter != NULL);
+ }
+
+ if (pdhStatus == ERROR_SUCCESS) {
+ // write the record terminator
+ bResult = WriteFile (pLog->hLogFileHandle,
+ (LPCVOID)szRecordTerminator,
+ dwRecordTerminatorLength,
+ &dwBytesWritten,
+ NULL);
+
+ if (!bResult) {
+ pdhStatus = GetLastError();
+ }
+ }
+ }
+
+ return pdhStatus;
+}
+
+static
+LONG
+CreateNewLogEntry (
+ IN LPCWSTR szLogFileName,
+ IN DWORD dwLogFileNameSize, // in chars, including term char
+ IN HQUERY hQuery,
+ IN DWORD dwMaxRecords
+)
+/*++
+ creates a new log entry and inserts it in the list of open log files
+
+--*/
+{
+ PLOG_INFO pNewLog;
+ DWORD dwSize;
+ LONG pdhStatus = ERROR_SUCCESS;
+
+ dwSize = dwLogFileNameSize;
+ dwSize *= sizeof (WCHAR);
+ dwSize *= 2; // double to make room for cat file name
+ dwSize = DWORD_MULTIPLE (dwSize); // ... rounded to the next DWORD
+ dwSize += sizeof (LOG_INFO); // + room for the data block
+
+ pNewLog = &LogEntry;
+
+ // set length field (this is used more for validation
+ // than anything else
+ pNewLog->dwLength = sizeof (LOG_INFO);
+ // append filename strings immediately after this block
+ pNewLog->szLogFileName = (LPWSTR)(&pNewLog[1]);
+ lstrcpyW (pNewLog->szLogFileName, szLogFileName);
+ // locate catalog name immediately after log file name
+ pNewLog->szCatFileName = pNewLog->szLogFileName + dwLogFileNameSize;
+ // FIXFIX: for now they are the same, later the log file extension
+ // will be replaced with the catalog file extenstion
+ lstrcpyW (pNewLog->szCatFileName, szLogFileName);
+ // initialize the file handles
+ pNewLog->hLogFileHandle = INVALID_HANDLE_VALUE;
+ pNewLog->hCatFileHandle = INVALID_HANDLE_VALUE;
+
+ // assign the query
+ pNewLog->hQuery = hQuery;
+
+ pNewLog->dwMaxRecords = dwMaxRecords;
+
+ pNewLog->dwLogFormat = 0; // for now
+
+ return pdhStatus;
+}
+
+static
+LONG
+OpenOutputLogFile (
+ IN PLOG_INFO pLog,
+ IN DWORD dwAccessFlags,
+ IN LPDWORD lpdwLogType
+)
+{
+ LONG Win32Error;
+ LONG pdhStatus = ERROR_SUCCESS;
+ DWORD dwFileCreate;
+
+ // open file for output based on the specified access flags
+
+ if (pdhStatus == ERROR_SUCCESS) {
+ switch (dwAccessFlags & LOG_CREATE_MASK) {
+ case LOG_CREATE_NEW:
+ dwFileCreate = CREATE_NEW;
+ break;
+
+ case LOG_CREATE_ALWAYS:
+ dwFileCreate = CREATE_ALWAYS;
+ break;
+
+ case LOG_OPEN_EXISTING:
+ dwFileCreate = OPEN_EXISTING;
+ break;
+
+ case LOG_OPEN_ALWAYS:
+ dwFileCreate = OPEN_ALWAYS;
+ break;
+
+ default:
+ // unrecognized value
+ pdhStatus = PDH_INVALID_ARGUMENT;
+ break;
+ }
+ }
+
+ if (pdhStatus == ERROR_SUCCESS) {
+ pLog->hLogFileHandle = CreateFileW (
+ pLog->szLogFileName,
+ GENERIC_WRITE, // write access for output
+ FILE_SHARE_READ, // allow read sharing
+ NULL, // default security
+ dwFileCreate,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL); // no template file
+
+ if (pLog->hLogFileHandle == INVALID_HANDLE_VALUE) {
+ Win32Error = GetLastError();
+ }
+ }
+
+ if (pdhStatus == ERROR_SUCCESS) {
+ // the file opened successfully so update the data structure
+ // this assumes the access flags are in the HIWORD and the...
+ pLog->dwLogFormat = dwAccessFlags & LOG_ACCESS_MASK;
+ // the type id is in the LOWORD
+ pLog->dwLogFormat |= *lpdwLogType;
+
+ // call any type-specific open functions
+ switch (LOWORD(pLog->dwLogFormat)) {
+ case OPD_CSV_FILE:
+ case OPD_TSV_FILE:
+ pdhStatus = OpenOutputTextLog(pLog);
+ break;
+
+ default:
+ pdhStatus = ERROR_NOT_SUPPORTED;
+ break;
+ }
+ }
+ return pdhStatus;
+}
+
+static
+LONG
+WriteLogHeader (
+ IN PLOG_INFO pLog
+)
+{
+ LONG pdhStatus;
+
+ switch (LOWORD(pLog->dwLogFormat)) {
+ case OPD_CSV_FILE:
+ case OPD_TSV_FILE:
+ pdhStatus = WriteTextLogHeader (pLog);
+ break;
+
+ default:
+ pdhStatus = ERROR_NOT_SUPPORTED;
+ break;
+ }
+ return pdhStatus;
+
+}
+
+static
+LONG
+CloseAndDeleteLogEntry (
+ IN PLOG_INFO pLog,
+ IN DWORD dwFlags
+)
+{
+ LONG pdhStatus = ERROR_SUCCESS;
+
+ // call any type-specific open functions
+ switch (LOWORD(pLog->dwLogFormat)) {
+ case OPD_CSV_FILE:
+ case OPD_TSV_FILE:
+ pdhStatus = CloseTextLog(pLog);
+ break;
+
+ default:
+ pdhStatus = ERROR_NOT_SUPPORTED;
+ break;
+ }
+
+ if (pdhStatus == ERROR_SUCCESS) {
+ if (pLog->lpMappedFileBase != NULL) {
+ UnmapViewOfFile (pLog->lpMappedFileBase);
+ }
+
+ if (pLog->hMappedLogFile != NULL) {
+ CloseHandle (pLog->hMappedLogFile);
+ }
+
+ if (pLog->hLogFileHandle != INVALID_HANDLE_VALUE) {
+ CloseHandle (pLog->hLogFileHandle);
+ }
+
+ if (pLog->hCatFileHandle != INVALID_HANDLE_VALUE) {
+
+ CloseHandle (pLog->hCatFileHandle);
+ }
+
+ if ((dwFlags & FLAGS_CLOSE_QUERY) == FLAGS_CLOSE_QUERY) {
+ pdhStatus = PdhCloseQuery (pLog->hQuery);
+ }
+ }
+
+ return pdhStatus;
+}
+
+//
+// Local utility functions
+//
+
+LONG __stdcall
+OpenLogW (
+ IN LPCWSTR szLogFileName,
+ IN DWORD dwAccessFlags,
+ IN LPDWORD lpdwLogType,
+ IN HQUERY hQuery,
+ IN DWORD dwMaxRecords
+)
+{
+ DWORD dwFileNameSize;
+ LONG pdhStatus = ERROR_SUCCESS;
+ DWORD dwLocalLogType;
+ PLOG_INFO pLog = &LogEntry;
+
+ try {
+ // test the parameters before continuing
+ if (szLogFileName != NULL) {
+ dwFileNameSize = lstrlenW (szLogFileName) + 1;
+ if (dwFileNameSize > 1) {
+ if (lpdwLogType != NULL) {
+ dwLocalLogType = *lpdwLogType; // test read
+ *lpdwLogType = 0; // test write to buffer
+ *lpdwLogType = dwLocalLogType; // restore value
+ } else {
+ // required parameter is missing
+ pdhStatus = PDH_INVALID_ARGUMENT;
+ }
+ } else {
+ // empty file name
+ pdhStatus = PDH_INVALID_ARGUMENT;
+ }
+ } else {
+ // required parameter is missing
+ pdhStatus = PDH_INVALID_ARGUMENT;
+ }
+ } except (EXCEPTION_EXECUTE_HANDLER) {
+ // something failed so give up here
+ pdhStatus = PDH_INVALID_ARGUMENT;
+ }
+
+ if (pdhStatus == ERROR_SUCCESS) {
+ // create a log entry
+ pdhStatus = CreateNewLogEntry (
+ szLogFileName,
+ dwFileNameSize,
+ hQuery,
+ dwMaxRecords);
+
+ // open the file
+ if (pdhStatus == ERROR_SUCCESS) {
+ // dispatch based on read/write attribute
+ if ((dwAccessFlags & LOG_READ_ACCESS) ==
+ LOG_READ_ACCESS) {
+ pdhStatus = ERROR_NOT_SUPPORTED;
+ } else if ((dwAccessFlags & LOG_WRITE_ACCESS) ==
+ LOG_WRITE_ACCESS) {
+ pdhStatus = OpenOutputLogFile (pLog,
+ dwAccessFlags, &dwLocalLogType);
+ if (pdhStatus == ERROR_SUCCESS) {
+ pdhStatus = WriteLogHeader (pLog);
+ }
+ } else {
+ pdhStatus = PDH_INVALID_ARGUMENT;
+ }
+ if (pdhStatus == ERROR_SUCCESS) {
+ // return handle to caller
+ *lpdwLogType = dwLocalLogType;
+ }
+ }
+ }
+
+ return pdhStatus;
+}
+
+LONG __stdcall
+UpdateLog (
+ IN LPDWORD pdwSampleTime)
+{
+ LONG pdhStatus;
+ SYSTEMTIME st;
+ LONGLONG llStartTime = 0;
+ LONGLONG llFinishTime = 0;
+ PLOG_INFO pLog = &LogEntry;
+
+ *pdwSampleTime = 0;
+
+ if (TRUE) {
+ // get the timestamp and update the log's query, then write the data
+ // to the log file in the appropriate format
+ GetLocalFileTime (&st, &llStartTime);
+
+ // update data samples
+ pdhStatus = PdhCollectQueryData (pLog->hQuery);
+
+ // write data to log file
+ pdhStatus = WriteTextLogRecord (pLog, &st);
+
+ GetLocalFileTime (&st, &llFinishTime);
+
+ *pdwSampleTime = (DWORD)((llFinishTime - llStartTime) / 10000L);
+ }
+
+ return pdhStatus;
+}
+
+LONG __stdcall
+CloseLog(
+ IN DWORD dwFlags
+)
+{
+ LONG pdhStatus;
+ PLOG_INFO pLog;
+
+ pLog = &LogEntry;
+ pdhStatus = CloseAndDeleteLogEntry (pLog, dwFlags);
+ memset (pLog, 0, sizeof(LOG_INFO));
+
+ return pdhStatus;
+}
+
+LONG __stdcall
+GetLogFileSize (
+ IN LONGLONG *llSize
+)
+{
+ LONG pdhStatus = ERROR_SUCCESS;
+ PLOG_INFO pLog;
+ UINT nErrorMode;
+ DWORD dwFileSizeLow = 0;
+ DWORD dwFileSizeHigh = 0;
+ LONGLONG llFileLength;
+ DWORD dwError;
+
+ // test return argument
+ try {
+ // test access to the user's buffer.
+ llFileLength = *llSize;
+ *llSize = 0;
+ *llSize = llFileLength;
+ } except (EXCEPTION_EXECUTE_HANDLER) {
+ pdhStatus = PDH_INVALID_ARGUMENT;
+ return pdhStatus;
+ }
+
+ if (TRUE) {
+ pLog = &LogEntry;
+ // disable windows error message popup
+ nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
+ if (pLog->hLogFileHandle != INVALID_HANDLE_VALUE) {
+ dwFileSizeLow = GetFileSize (pLog->hLogFileHandle, &dwFileSizeHigh);
+ // test for error
+ if ((dwFileSizeLow == 0xFFFFFFFF) &&
+ ((dwError = GetLastError()) != NO_ERROR)) {
+ // then we couldn't get the file size
+ pdhStatus = ERROR_OPEN_FAILED;
+ } else {
+ if (dwFileSizeHigh > 0) {
+ llFileLength = dwFileSizeHigh << (sizeof(DWORD) * 8);
+ } else {
+ llFileLength = 0;
+ }
+ llFileLength += dwFileSizeLow;
+ // write to the caller' buffer
+ *llSize = llFileLength;
+ }
+ } else {
+ pdhStatus = ERROR_OPEN_FAILED;
+ }
+ SetErrorMode (nErrorMode); // restore old error mode
+ } else {
+ pdhStatus = PDH_INVALID_HANDLE;
+ }
+
+ return pdhStatus;
+}
+
+
diff --git a/private/sdktools/perflog/pdlsvc/logutils.h b/private/sdktools/perflog/pdlsvc/logutils.h
new file mode 100644
index 000000000..70e787ce3
--- /dev/null
+++ b/private/sdktools/perflog/pdlsvc/logutils.h
@@ -0,0 +1,36 @@
+#ifndef _LOG_UTILS_H_
+#define _LOG_UTILS_H_
+
+#define LOG_READ_ACCESS 0x00010000
+#define LOG_WRITE_ACCESS 0x00020000
+#define LOG_ACCESS_MASK 0x000F0000
+#define LOG_CREATE_NEW 0x00000001
+#define LOG_CREATE_ALWAYS 0x00000002
+#define LOG_OPEN_ALWAYS 0x00000003
+#define LOG_OPEN_EXISTING 0x00000004
+#define LOG_CREATE_MASK 0x0000000F
+
+#define FLAGS_CLOSE_QUERY 0x00000001
+
+#define DWORD_MULTIPLE(x) ((((x)+sizeof(DWORD)-1)/sizeof(DWORD))*sizeof(DWORD))
+#define CLEAR_FIRST_FOUR_BYTES(x) *(DWORD *)(x) = 0L
+
+
+LONG __stdcall
+OpenLogW (
+ IN LPCWSTR szLogFileName,
+ IN DWORD dwAccessFlags,
+ IN LPDWORD lpdwLogType,
+ IN HQUERY hQuery,
+ IN DWORD dwMaxRecords
+);
+
+LONG __stdcall UpdateLog (
+ IN LPDWORD pdwSampleTime);
+
+LONG __stdcall CloseLog(IN DWORD dwFlags);
+
+LONG __stdcall GetLogFileSize (IN LONGLONG *llSize);
+
+#endif // _LOG_UTILS_H_
+
diff --git a/private/sdktools/perflog/pdlsvc/makefile b/private/sdktools/perflog/pdlsvc/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/sdktools/perflog/pdlsvc/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/sdktools/perflog/pdlsvc/makefile.inc b/private/sdktools/perflog/pdlsvc/makefile.inc
new file mode 100644
index 000000000..9563f3097
--- /dev/null
+++ b/private/sdktools/perflog/pdlsvc/makefile.inc
@@ -0,0 +1,10 @@
+!IFNDEF BUILDMSG
+BUILDMSG=
+!ENDIF
+
+!IF "$(BUILDMSG)" != ""
+ @ech ; $(BUILDMSG) ;
+!ENDIF
+
+.\pdlmsg.h .\msg00001.bin .\pdlmsg.rc : .\pdlmsg.mc
+ mc -v pdlmsg.mc
diff --git a/private/sdktools/perflog/pdlsvc/pdlmsg.mc b/private/sdktools/perflog/pdlsvc/pdlmsg.mc
new file mode 100644
index 000000000..5cdd807ac
--- /dev/null
+++ b/private/sdktools/perflog/pdlsvc/pdlmsg.mc
@@ -0,0 +1,131 @@
+;/*++ BUILD Version: 0001 // Increment this if a change has global effects
+;
+;Copyright (c) 1996 Microsoft Corporation
+;
+;Module Name:
+;
+; pdlmsg.h
+; (generated from pdlmsg.mc)
+;
+;Abstract:
+;
+; Event message definititions used by routines by PerfDataLog Service
+;
+;Created:
+;
+; 12-Apr-96 Bob Watson (a-robw)
+;
+;Revision History:
+;
+;--*/
+;#ifndef _PDL_MSG_H_
+;#define _PDL_MSG_H_
+MessageIdTypedef=DWORD
+;//
+;// PerfDataLog Service messages
+;//
+SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
+ Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
+ Warning=0x2:STATUS_SEVERITY_WARNING
+ Error=0x3:STATUS_SEVERITY_ERROR
+ )
+;//
+;//
+;// Informational messages
+;//
+;// None
+;//
+;// Warning Messages
+;// These messages are returned when the function has completed
+;// successfully but the results may be different than expected.
+;//
+;// MessageId=1000
+;//
+;// Error Messages
+;// These messages are returned when the function could not complete
+;// as requested and some corrective action may be required by the
+;// the caller or the user.
+;//
+MessageId=2000
+Severity=Error
+Facility=Application
+SymbolicName=PERFLOG_UNABLE_START_DISPATCHER
+Language=English
+Unable to initialize the service. Win32 error code returned is in the data.
+.
+MessageId=+1
+Severity=Error
+Facility=Application
+SymbolicName=PERFLOG_UNABLE_REGISTER_HANDLER
+Language=English
+Unable to register the Service Control Handler function. Win32 error code returned
+is in the data.
+.
+MessageId=+1
+Severity=Error
+Facility=Application
+SymbolicName=PERFLOG_UNABLE_OPEN_LOG_QUERY
+Language=English
+Unable to open the Log Query key in the registry. Error code is in the data.
+.
+MessageId=+1
+Severity=Warning
+Facility=Application
+SymbolicName=PERFLOG_UNABLE_READ_LOG_QUERY
+Language=English
+Unable to read the Log Query configuration of the %1 query entry.
+This query will not be started.
+The Error code returned is shown in the data.
+.
+MessageId=+1
+Severity=Warning
+Facility=Application
+SymbolicName=PERFLOG_UNABLE_ALLOCATE_DATABLOCK
+Language=English
+Unable to allocate a data block for the %1 query entry.
+This query will not be started.
+The Error code returned is shown in the data.
+.
+MessageId=+1
+Severity=Warning
+Facility=Application
+SymbolicName=PERFLOG_UNABLE_START_THREAD
+Language=English
+Unable to start the logging thread for the %1 query entry.
+The Error code returned is shown in the data.
+.
+MessageId=+1
+Severity=Error
+Facility=Application
+SymbolicName=PERFLOG_UNABLE_READ_COUNTER_LIST
+Language=English
+Unable to read the list of counters to log for query %1 from the registry.
+This query will not be started. The Error code returned is shown in the data.
+.
+MessageId=+1
+Severity=ERROR
+Facility=Application
+SymbolicName=PERFLOG_UNABLE_ALLOC_COUNTER_LIST
+Language=English
+Unable to allocate the memory for the counter list of query %1. This
+query will not be started. The Error code returned is shown in the data.
+.
+MessageId=+1
+Severity=INFORMATIONAL
+Facility=Application
+SymbolicName=PERFLOG_LOGGING_QUERY
+Language=English
+Query %1 has been started or restarted and is logging data to file %2.
+.
+MessageId=+1
+Severity=ERROR
+Facility=Application
+SymbolicName=PERFLOG_UNABLE_UPDATE_LOG
+Language=English
+An error occured while trying to update the log with the current value.
+The service is stopping and the error code returned is in the data.
+Correct the error and restart the service.
+.
+;#endif //_PDL_MSG_H_
+;// end of generated file
+ \ No newline at end of file
diff --git a/private/sdktools/perflog/pdlsvc/pdlsvc.c b/private/sdktools/perflog/pdlsvc/pdlsvc.c
new file mode 100644
index 000000000..ba905c140
--- /dev/null
+++ b/private/sdktools/perflog/pdlsvc/pdlsvc.c
@@ -0,0 +1,392 @@
+/*++
+
+Copyright (c) 1996 Microsoft Corporation
+
+Module Name:
+
+ pdlsvc.c
+
+Abstract:
+
+ service to log performance data
+
+Author:
+
+ Bob Watson (a-robw) 10 Apr 96
+
+Revision History:
+
+--*/
+#ifndef UNICODE
+#define UNICODE 1
+#endif
+
+#ifndef _UNICODE
+#define _UNICODE 1
+#endif
+
+//
+// Windows Include files
+//
+#include <windows.h>
+#include <tchar.h>
+
+#include "pdlsvc.h"
+#include "pdlmsg.h"
+
+// Global variables used by all modules
+HANDLE hEventLog = NULL;
+PLOG_COUNTER_INFO pFirstCounter = NULL;
+
+SERVICE_STATUS_HANDLE hPerfLogStatus;
+SERVICE_STATUS ssPerfLogStatus;
+
+// Static variables used by this module only
+static LPLOG_THREAD_DATA pFirstThread = NULL;
+static HANDLE *pThreadHandleArray = NULL;
+static DWORD dwHandleCount = 0;
+static DWORD dwMaxHandleCount = 0;
+
+// this is for the time being, until full multiple log query
+// support is added
+#define LOCAL_HANDLE_COUNT 1
+static HANDLE LocalThreadArray[LOCAL_HANDLE_COUNT];
+
+// functions
+
+void FreeThreadData (
+ IN LPLOG_THREAD_DATA pThisThread
+)
+{
+ if (pThisThread->next != NULL) {
+ // free the "downstream" entries
+ FreeThreadData (pThisThread->next);
+ pThisThread->next = NULL;
+ }
+ // now free this entry
+ if (pThisThread->mszCounterList != NULL) {
+ G_FREE (pThisThread->mszCounterList);
+ pThisThread->mszCounterList = NULL;
+ }
+
+ if (pThisThread->hExitEvent != NULL) {
+ CloseHandle (pThisThread->hExitEvent);
+ pThisThread->hExitEvent = NULL;
+ }
+
+ if (pThisThread->hKeyQuery != NULL) {
+ RegCloseKey (pThisThread->hKeyQuery);
+ pThisThread->hKeyQuery = NULL;
+ }
+
+ G_FREE (pThisThread);
+}
+
+void PerfDataLogServiceControlHandler(
+ IN DWORD dwControl
+)
+{
+ LPLOG_THREAD_DATA pThisThread;
+
+ switch (dwControl) {
+ case SERVICE_CONTROL_SHUTDOWN:
+ case SERVICE_CONTROL_STOP:
+ // stop logging & close queries and files
+ // set stop event for all running threads
+ pThisThread = pFirstThread;
+ while (pThisThread != NULL) {
+ SetEvent (pThisThread->hExitEvent);
+ pThisThread = pThisThread->next;
+ }
+ break;
+ case SERVICE_CONTROL_PAUSE:
+ // stop logging, close queries and files
+ // not supported, yet
+ break;
+ case SERVICE_CONTROL_CONTINUE:
+ // reload configuration and restart logging
+ // not supported, yet
+ break;
+ case SERVICE_CONTROL_INTERROGATE:
+ // update current status
+ default:
+ // report to event log that an unrecognized control
+ // request was received.
+ ;
+ }
+}
+
+void
+PerfDataLogServiceStart (
+ IN DWORD argc,
+ IN LPTSTR *argv
+)
+{
+ LONG lStatus;
+ HKEY hKeyLogQueries;
+ HKEY hKeyThisLogQuery;
+ DWORD dwQueryIndex;
+ TCHAR szQueryNameBuffer[MAX_PATH];
+ DWORD dwQueryNameBufferSize;
+ TCHAR szQueryClassBuffer[MAX_PATH];
+ DWORD dwQueryClassBufferSize;
+ LPLOG_THREAD_DATA lpThreadData;
+ HANDLE hThread;
+ LPTSTR szStringArray[2];
+ DWORD dwThreadId;
+
+ ssPerfLogStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ ssPerfLogStatus.dwCurrentState = SERVICE_START_PENDING;
+ ssPerfLogStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
+// SERVICE_ACCEPT_PAUSE_CONTINUE |
+ SERVICE_ACCEPT_SHUTDOWN;
+ ssPerfLogStatus.dwWin32ExitCode = 0;
+ ssPerfLogStatus.dwServiceSpecificExitCode = 0;
+ ssPerfLogStatus.dwCheckPoint = 0;
+ ssPerfLogStatus.dwWaitHint = 0;
+
+ hPerfLogStatus = RegisterServiceCtrlHandler (
+ TEXT("PerfDataLog"), PerfDataLogServiceControlHandler);
+
+ if (hPerfLogStatus == (SERVICE_STATUS_HANDLE)0) {
+ lStatus = GetLastError();
+ ReportEvent (hEventLog,
+ EVENTLOG_ERROR_TYPE,
+ 0,
+ PERFLOG_UNABLE_REGISTER_HANDLER,
+ NULL,
+ 0,
+ sizeof(DWORD),
+ NULL,
+ (LPVOID)&lStatus);
+ // this is fatal so bail out
+ return;
+ }
+
+ // registered the service successfully, so load the log queries
+ // assign the handle buffer
+ pThreadHandleArray = &LocalThreadArray[0];
+ dwMaxHandleCount = LOCAL_HANDLE_COUNT;
+ // open (each) query
+ lStatus = RegOpenKeyEx (
+ HKEY_LOCAL_MACHINE,
+ TEXT("SYSTEM\\CurrentControlSet\\Services\\PerfDataLog\\Log Queries"),
+ 0L,
+ KEY_READ,
+ &hKeyLogQueries);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // unable to read the log query information from the registry
+ lStatus = GetLastError();
+ ReportEvent (hEventLog,
+ EVENTLOG_ERROR_TYPE,
+ 0,
+ PERFLOG_UNABLE_OPEN_LOG_QUERY,
+ NULL,
+ 0,
+ sizeof(DWORD),
+ NULL,
+ (LPVOID)&lStatus);
+
+ // we can't start the service with out the evnt log.
+ ssPerfLogStatus.dwCurrentState = SERVICE_STOPPED;
+ SetServiceStatus (hPerfLogStatus, &ssPerfLogStatus);
+
+ return;
+ }
+
+ // enumerate and start the queries in the registry
+ dwQueryIndex = 0;
+ *szQueryNameBuffer = 0;
+ dwQueryNameBufferSize = MAX_PATH;
+ *szQueryClassBuffer;
+ dwQueryClassBufferSize = MAX_PATH;
+ while ((lStatus = RegEnumKeyEx (
+ hKeyLogQueries,
+ dwQueryIndex,
+ szQueryNameBuffer,
+ &dwQueryNameBufferSize,
+ NULL,
+ szQueryClassBuffer,
+ &dwQueryClassBufferSize,
+ NULL)) != ERROR_NO_MORE_ITEMS) {
+
+ // open this key
+ lStatus = RegOpenKeyEx (
+ hKeyLogQueries,
+ szQueryNameBuffer,
+ 0L,
+ KEY_READ | KEY_WRITE,
+ &hKeyThisLogQuery);
+
+ if (lStatus != ERROR_SUCCESS) {
+ szStringArray[0] = szQueryNameBuffer;
+ ReportEvent (hEventLog,
+ EVENTLOG_WARNING_TYPE,
+ 0,
+ PERFLOG_UNABLE_READ_LOG_QUERY,
+ NULL,
+ 1,
+ sizeof(DWORD),
+ szStringArray,
+ (LPVOID)&lStatus);
+ // skip to next item
+ goto CONTINUE_ENUM_LOOP;
+ }
+
+ // update the service status
+ ssPerfLogStatus.dwCheckPoint++;
+ SetServiceStatus (hPerfLogStatus, &ssPerfLogStatus);
+
+ // allocate a thread info block.
+ lpThreadData = G_ALLOC (sizeof(LOG_THREAD_DATA));
+ if (lpThreadData == NULL) {
+ lStatus = GetLastError();
+ szStringArray[0] = szQueryNameBuffer;
+ ReportEvent (hEventLog,
+ EVENTLOG_WARNING_TYPE,
+ 0,
+ PERFLOG_UNABLE_ALLOCATE_DATABLOCK,
+ NULL,
+ 1,
+ sizeof(DWORD),
+ szStringArray,
+ (LPVOID)&lStatus);
+ goto CONTINUE_ENUM_LOOP;
+ }
+
+ // initialize the thread data block
+ lpThreadData->hKeyQuery = hKeyThisLogQuery;
+ lpThreadData->hExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ lpThreadData->bReloadNewConfig = FALSE;
+ lstrcpy (lpThreadData->szQueryName, szQueryNameBuffer);
+
+ // start logging thread
+ hThread = CreateThread (
+ NULL, 0, LoggingThreadProc,
+ (LPVOID)lpThreadData, 0, &dwThreadId);
+
+ if (hThread != NULL) {
+ // add it to the list and continue
+ if (pFirstThread == NULL) {
+ // then this is the first thread so add it
+ lpThreadData->next = NULL;
+ pFirstThread = lpThreadData;
+ } else {
+ // insert this at the head of the list since
+ // that's the easiest and the order isn't
+ // really important
+ lpThreadData->next = pFirstThread;
+ pFirstThread = lpThreadData;
+ }
+ // add thread to array for termination wait
+ if (dwHandleCount < dwMaxHandleCount) {
+ pThreadHandleArray[dwHandleCount++] = hThread;
+ } else {
+ // realloc buffer and try again
+ // this will be added when multi-query
+ // support is added. for now we'll ignore
+ // ones that don't fit.
+ }
+ lpThreadData = NULL; //clear for next lap
+ } else {
+ // unable to start thread
+ lStatus = GetLastError();
+ szStringArray[0] = szQueryNameBuffer;
+ ReportEvent (hEventLog,
+ EVENTLOG_WARNING_TYPE,
+ 0,
+ PERFLOG_UNABLE_START_THREAD,
+ NULL,
+ 1,
+ sizeof(DWORD),
+ szStringArray,
+ (LPVOID)&lStatus);
+ }
+CONTINUE_ENUM_LOOP:
+ // prepare for next loop
+ dwQueryIndex++;
+ // for now we just do the first item in the list
+ // the full multiple log query feature will be
+ // added later.
+ if (dwQueryIndex > 0) break;
+ // otherwise we would continue here
+ *szQueryNameBuffer = 0;
+ dwQueryNameBufferSize = MAX_PATH;
+ *szQueryClassBuffer;
+ dwQueryClassBufferSize = MAX_PATH;
+ } // end enumeration of log queries
+
+ // service is now started
+ ssPerfLogStatus.dwCurrentState = SERVICE_RUNNING;
+ ssPerfLogStatus.dwCheckPoint++;
+ SetServiceStatus (hPerfLogStatus, &ssPerfLogStatus);
+
+ // wait for (all) timing and logging threads to complete
+ lStatus = WaitForMultipleObjects (dwHandleCount,
+ pThreadHandleArray, TRUE, INFINITE);
+
+ ssPerfLogStatus.dwCurrentState = SERVICE_STOP_PENDING;
+ SetServiceStatus (hPerfLogStatus, &ssPerfLogStatus);
+
+ // when here, all logging threads have terminated so the
+ // memory can be released and the service can exit and shutdown.
+ for (dwQueryIndex = 0; dwQueryIndex < dwHandleCount; dwQueryIndex++) {
+ CloseHandle (pThreadHandleArray[dwQueryIndex]);
+ }
+
+ // release the dynamic memory
+ FreeThreadData (pFirstThread);
+
+ // and update the service status
+ ssPerfLogStatus.dwCurrentState = SERVICE_STOPPED;
+ SetServiceStatus (hPerfLogStatus, &ssPerfLogStatus);
+
+ if (hEventLog != NULL) CloseHandle (hEventLog);
+
+ return;
+}
+
+void
+_CRTAPI1 main(void)
+/*++
+
+main
+
+
+
+Arguments
+
+
+ReturnValue
+
+ 0 (ERROR_SUCCESS) if command was processed
+ Non-Zero if command error was detected.
+
+--*/
+{
+ LONG lStatus;
+
+ SERVICE_TABLE_ENTRY DispatchTable[] = {
+ {TEXT("PerfDataLog"), PerfDataLogServiceStart },
+ {NULL, NULL }
+ };
+
+ hEventLog = RegisterEventSource (NULL, TEXT("PerfDataLog"));
+
+ if (!StartServiceCtrlDispatcher (DispatchTable)) {
+ lStatus = GetLastError();
+ // log failure to event log
+ ReportEvent (hEventLog,
+ EVENTLOG_ERROR_TYPE,
+ 0,
+ PERFLOG_UNABLE_START_DISPATCHER,
+ NULL,
+ 0,
+ sizeof(DWORD),
+ NULL,
+ (LPVOID)&lStatus);
+ }
+ return;
+}
+
diff --git a/private/sdktools/perflog/pdlsvc/pdlsvc.h b/private/sdktools/perflog/pdlsvc/pdlsvc.h
new file mode 100644
index 000000000..97867b520
--- /dev/null
+++ b/private/sdktools/perflog/pdlsvc/pdlsvc.h
@@ -0,0 +1,69 @@
+/*
+ pdlsvc.h
+
+*/
+#include <pdh.h>
+#include <common.h>
+
+#ifndef _PDLSVC_H_
+#define _PDLSVC_H_
+
+#define G_ALLOC(size) HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, size)
+#define G_FREE(ptr) HeapFree (GetProcessHeap(), 0, ptr)
+
+// definitionsdwAutoNameFormat
+typedef struct _LOG_THREAD_DATA {
+ // These fields are written by the main thread
+ // and read by the logging thread
+ struct _LOG_THREAD_DATA *next;
+ HKEY hKeyQuery;
+ HANDLE hExitEvent;
+ BOOL bReloadNewConfig;
+ TCHAR szQueryName[MAX_PATH];
+ // these fields are written and read by the logging thread
+ DWORD dwTimeInterval; // in seconds
+ LPTSTR mszCounterList;
+ DWORD dwLogType;
+ DWORD dwAutoNameFormat;
+ DWORD dwRenameIntervalCount;
+ DWORD dwRenameIntervalUnits;
+ DWORD dwCurrentSerialNumber;
+} LOG_THREAD_DATA, FAR * LPLOG_THREAD_DATA;
+
+typedef struct _LOG_COUNTER_INFO {
+ struct _LOG_COUNTER_INFO *next;
+ HCOUNTER hCounter;
+} LOG_COUNTER_INFO, * PLOG_COUNTER_INFO;
+
+extern PLOG_COUNTER_INFO pFirstCounter;
+
+// global variables
+extern HANDLE hEventLog;
+
+extern SERVICE_STATUS_HANDLE hPerfLogStatus;
+extern SERVICE_STATUS ssPerfLogStatus;
+
+// pdlsvc.c
+void PerfDataLogServiceControlHandler(
+ IN DWORD dwControl
+);
+
+void
+PerfDataLogServiceStart (
+ IN DWORD argc,
+ IN LPTSTR *argv
+);
+
+void
+_CRTAPI1 main(void);
+
+// logthred.c
+
+DWORD
+LoggingThreadProc (
+ IN LPVOID lpThreadArg
+);
+
+
+#endif //_PDLSVC_H_
+
diff --git a/private/sdktools/perflog/pdlsvc/pdlsvc.rc b/private/sdktools/perflog/pdlsvc/pdlsvc.rc
new file mode 100644
index 000000000..405a2fe4a
--- /dev/null
+++ b/private/sdktools/perflog/pdlsvc/pdlsvc.rc
@@ -0,0 +1,12 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Performance Data Log Service"
+#define VER_INTERNALNAME_STR "PDLSVC.EXE"
+#define VER_ORIGINALFILENAME_STR "PDLSVC.EXE"
+
+#include "common.ver"
+#include "pdlmsg.rc"
+ \ No newline at end of file
diff --git a/private/sdktools/perflog/pdlsvc/sources b/private/sdktools/perflog/pdlsvc/sources
new file mode 100644
index 000000000..4f7940144
--- /dev/null
+++ b/private/sdktools/perflog/pdlsvc/sources
@@ -0,0 +1,50 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=sysmon
+MINORCOMP=pdlsvc
+GPSIZE=32
+
+INCLUDES=.;..\pdlcnfig
+
+TARGETNAME=pdlsvc
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+SOURCES=pdlsvc.c \
+ logthred.c \
+ logutils.c \
+ pdlsvc.rc
+
+UMTYPE=console
+UMAPPL=pdlsvc
+UMLIBS= obj\*\pdlsvc.res \
+ obj\*\pdlsvc.lib \
+ $(BASEDIR)\public\sdk\lib\*\pdh.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib
+
+NTTARGETFILE0=pdlmsg.h\
+ pdlmsg.rc
+ \ No newline at end of file