HRESULT GetFileName(wchar_t *FileName, UINT FileNameSize, WCHAR* instanceName, SensorType senserID)
{
	wchar_t DevIdOut[20];
	HRESULT hr;
	GetDevIdforFile(instanceName, DevIdOut);

    // Get the time
    wchar_t timeString[MAX_PATH];
	wchar_t dateString[MAX_PATH];
    GetTimeFormatEx(NULL, TIME_FORCE24HOURFORMAT, NULL, L"hh'-'mm'-'ss", timeString, _countof(timeString));
	GetDateFormatEx(NULL, 0, NULL, L"yyyy'-'MMM'-'dd", dateString, _countof(dateString), NULL);

	// File name will be DeviceConnectID-KinectAudio-HH-MM-SS.wav
	switch (senserID)
	{
	case AudioSensor:
		hr=StringCchPrintfW(FileName, FileNameSize, L"%s\\KinectAudio\\Audio-%s-%s-%s.wav", knownPath, DevIdOut, dateString, timeString);
		break;
	case RGBSensor:
		hr=StringCchPrintfW(FileName, FileNameSize, L"%s\\KinectRGB\\RGB-%s-%s-%s.avi", knownPath, DevIdOut, dateString, timeString);
		break;
	case DepthSensor:
		hr=StringCchPrintfW(FileName, FileNameSize, L"%s\\KinectDepth\\Depth-%s-%s-%s.avi", knownPath, DevIdOut, dateString, timeString);
		break;
	case SpeechRecog:
		hr=StringCchPrintfW(FileName, FileNameSize, L"%s\\KinectSpeechRecog\\SpeechRecog-%s-%s-%s.txt", knownPath, DevIdOut, dateString, timeString);
		break;
	default:
		break;
	}
    return hr;
}
Example #2
0
 inline std::wstring datetime_cast<std::wstring, CalendarDatetime, const wchar_t*>(const CalendarDatetime& dt, const wchar_t* const& format)
 {
     const auto wdt = datetime_cast<win::CalendarDatetime>(dt);
     std::wstring sdt{ format };
     wchar_t datetimeBuffer[128] = {};
     if (GetDateFormatEx(LOCALE_NAME_INVARIANT, 0, &wdt, sdt.c_str(), datetimeBuffer, _countof(datetimeBuffer), nullptr) > 0)
         sdt = datetimeBuffer;
     if (GetTimeFormatEx(LOCALE_NAME_INVARIANT, 0, &wdt, sdt.c_str(), datetimeBuffer, _countof(datetimeBuffer)) > 0)
         sdt = datetimeBuffer;
     return sdt;
 }
Example #3
0
    std::string FormatTime(std::time_t timestamp)
    {
        SYSTEMTIME st = TimeToSystemTime(timestamp);

#    ifdef __USE_GETDATEFORMATEX__
        wchar_t time[20];
        GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &st, nullptr, time, sizeof(time));
        std::string result = String::ToUtf8(std::wstring(time));
#    else
        char time[20];
        GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, nullptr, time, sizeof(time));
        std::string result(time);
#    endif

        return result;
    }
Example #4
0
/// <summary>
/// Get the name of the file where screenshot will be stored.
/// </summary>
/// <param name="screenshotName">
/// [out] String buffer that will receive screenshot file name.
/// </param>
/// <param name="screenshotNameSize">
/// [in] Number of characters in screenshotName string buffer.
/// </param>
/// <returns>
/// S_OK on success, otherwise failure code.
/// </returns>
HRESULT GetScreenshotFileName(wchar_t *screenshotName, UINT screenshotNameSize)
{
    wchar_t *knownPath = NULL;
    HRESULT hr = SHGetKnownFolderPath(FOLDERID_Pictures, 0, NULL, &knownPath);

    if (SUCCEEDED(hr))
    {
        // Get the time
        wchar_t timeString[MAX_PATH];
        GetTimeFormatEx(NULL, 0, NULL, L"hh'-'mm'-'ss", timeString, _countof(timeString));

        // File name will be KinectSnapshot-HH-MM-SS.wav
        StringCchPrintfW(screenshotName, screenshotNameSize, L"%s\\KinectSnapshot-%s.bmp", knownPath, timeString);
    }

    CoTaskMemFree(knownPath);
    return hr;
}
Example #5
0
WString FileTimeToString(const FILETIME& filetime)
{
	SYSTEMTIME localSystemTime;
	FileTimeToSystemTime(&filetime, &localSystemTime);

	// Get the correct locale
	wchar_t localeName[LOCALE_NAME_MAX_LENGTH]={0};
	GetSystemDefaultLocaleName(localeName, sizeof(localeName)/sizeof(*localeName));

	// Get the localized date string
	wchar_t dateString[100]={0};
	GetDateFormatEx(localeName, DATE_SHORTDATE, &localSystemTime, NULL, dateString, sizeof(dateString)/sizeof(*dateString), NULL);

	// Get the localized time string
	wchar_t timeString[100]={0};
	GetTimeFormatEx(localeName, TIME_FORCE24HOURFORMAT | TIME_NOSECONDS, &localSystemTime, NULL, timeString, sizeof(timeString)/sizeof(*timeString));

	return dateString+WString(L" ")+timeString;
}
/// <summary>
/// Get the name of the file where screenshot will be stored.
/// </summary>
/// <param name="lpszFilePath">string buffer that will receive screenshot file name.</param>
/// <param name="nFilePathSize">number of characters in lpszFilePath string buffer.</param>
/// <returns>
/// S_OK on success, otherwise failure code.
/// </returns>
HRESULT CCoordinateMappingBasics::GetScreenshotFileName(LPWSTR lpszFilePath, UINT nFilePathSize)
{
    WCHAR* pszKnownPath = NULL;
    HRESULT hr = SHGetKnownFolderPath(FOLDERID_Pictures, 0, NULL, &pszKnownPath);

    if (SUCCEEDED(hr))
    {
        // Get the time
        WCHAR szTimeString[MAX_PATH];
        GetTimeFormatEx(NULL, 0, NULL, L"hh'-'mm'-'ss", szTimeString, _countof(szTimeString));

        // File name will be KinectScreenshotDepth-HH-MM-SS.bmp
        StringCchPrintfW(lpszFilePath, nFilePathSize, L"%s\\KinectScreenshot-CoordinateMapping-%s.bmp", pszKnownPath, szTimeString);
    }

    if (pszKnownPath)
    {
        CoTaskMemFree(pszKnownPath);
    }

    return hr;
}
Example #7
0
/// <summary>
/// Get the name of the file where screenshot will be stored.
/// </summary>
/// <param name="screenshotName">
/// [out] String buffer that will receive screenshot file name.
/// </param>
/// <param name="screenshotNameSize">
/// [in] Number of characters in screenshotName string buffer.
/// </param>
/// <returns>
/// S_OK on success, otherwise failure code.
/// </returns>
HRESULT GetScreenshotFileName(wchar_t *screenshotName, UINT screenshotNameSize,int shotType)
{
   wchar_t *knownPath = NULL;
    HRESULT hr = SHGetKnownFolderPath(FOLDERID_Pictures, 0, NULL, &knownPath);
	
      knownPath=L"..\\output";
    if (SUCCEEDED(hr))
    {
        // Get the time
        wchar_t timeString[MAX_PATH];
        GetTimeFormatEx(NULL,TIME_FORCE24HOURFORMAT, NULL, L"hh'-'mm'-'ss", timeString, _countof(timeString));

		// File name will be KinectColorShot-HH-MM-SS(shotType==0)
		//                or KinectDepthShot-HH-MM-SS(shotType==1)
        if(shotType==0)
        StringCchPrintfW(screenshotName, screenshotNameSize, L"%s\\KinectColorShot-%s.bmp", knownPath, timeString);
		else if(shotType==1)
        StringCchPrintfW(screenshotName, screenshotNameSize, L"%s\\KinectDepthShot-%s.bmp", knownPath, timeString);
    }

   // CoTaskMemFree(knownPath);
    return hr;
}
Example #8
0
    /// <summary>
    ///     Logs the hill climbing decision.
    /// </summary>
    /// <param name="recommendedSetting">
    ///     The control setting to be established.
    /// </param>
    /// <param name="transition">
    ///     The transition that is recommended by hill climbing.
    /// </param>
    /// <param name="numberOfSamples">
    ///     The number of sample points in this measurement, including invalid ones.
    /// </param>
    /// <param name="completionRate">
    ///     The number of completed units or work in that period of time.
    /// </param>
    /// <param name="arrivalRate">
    ///     The number of incoming units or work in that period of time.
    /// </param>
    /// <param name="queueLength">
    ///     The total length of the work queue.
    /// </param>
    /// <param name="throughput">
    ///     The throughput of the given instance.
    /// </param>
    void HillClimbing::LogData(unsigned int recommendedSetting, HillClimbingStateTransition transition, unsigned int numberOfSamples,
        unsigned int completionRate, unsigned int arrivalRate, unsigned int queueLength, double throughput)
    {
        //
        // First, log to memory so we can see it in the debugger
        //
        int index = (HillClimbingLogFirstIndex + HillClimbingLogSize) % HillClimbingLogCapacity;
        if (HillClimbingLogSize == HillClimbingLogCapacity)
        {
            HillClimbingLogFirstIndex = (HillClimbingLogFirstIndex + 1) % HillClimbingLogCapacity;
            HillClimbingLogSize--; //hide this slot while we update it
        }

        HillClimbingLogEntry * entry = &HillClimbingLog[index];
        unsigned int minimumSetting = m_pSchedulerProxy->MinHWThreads();
        unsigned int maximumSetting = m_pSchedulerProxy->DesiredHWThreads();

        entry->sampleCount = m_sampleCount;
        entry->currentTotalSampleCount = numberOfSamples;
        entry->throughput = throughput;
        entry->transition = transition;
        entry->currentControlSetting = m_currentControlSetting;
        entry->lastControlSetting = m_lastControlSetting;

        MeasuredHistory * currentHistory = GetHistory(m_currentControlSetting);
        entry->currentHistoryCount = currentHistory->Count();
        entry->currentHistoryMean = currentHistory->Mean();
        entry->currentHistoryStd = currentHistory->StandardDeviation();

        MeasuredHistory * lastHistory = GetHistory(m_lastControlSetting);
        entry->lastHistoryCount = lastHistory->Count();
        entry->lastHistoryMean = lastHistory->Mean();
        entry->lastHistoryStd = lastHistory->StandardDeviation();

        HillClimbingLogSize++;

        const int bufferSize = 180;
        const wchar_t * delim = L"*******************************************************";

        wchar_t dateBuffer[bufferSize];
        SYSTEMTIME time;
        GetLocalTime(&time);
        int dateLen = GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, dateBuffer, bufferSize);
        dateBuffer[dateLen-1] = L' ';
        GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, &time, NULL, dateBuffer + dateLen, bufferSize - dateLen);

        TRACE(CONCRT_TRACE_HILLCLIMBING, L"%ls\n Process: %u\n Scheduler: %d\n Date: %ls\n Number of samples: %d\n Number of samples in this measurement (including invalid): %d\n Completions: %d\n Arrivals: %d\n Queue length: %d\n Throughput: %.4f\n Transition: %ls\n Next random move: %ls\n Minimum: %d\n Maximum: %d\n Current setting: %d\n  * count: %d mean: %g dev: %g varm: %g\n Last setting: %d\n  * count: %d mean: %g dev: %g varm: %g\n -----\n Recommended setting: %d\n%ls\n",
            delim,
            GetCurrentProcessId(),
            m_id,
            dateBuffer,
            m_sampleCount,
            numberOfSamples,
            completionRate,
            arrivalRate,
            queueLength,
            throughput,
            HillClimbingTransitionNames[transition],
            m_nextRandomMoveIsUp ? L"Up" : L"Down",
            minimumSetting,
            maximumSetting,
            m_currentControlSetting,
            currentHistory->Count(),
            currentHistory->Mean(),
            currentHistory->StandardDeviation(),
            currentHistory->CoefficientOfVariationMean(),
            m_lastControlSetting,
            lastHistory->Count(),
            lastHistory->Mean(),
            lastHistory->StandardDeviation(),
            lastHistory->CoefficientOfVariationMean(),
            recommendedSetting,
            delim);
    }
Example #9
0
/// <summary>
/// Handle windows messages for the class instance
/// </summary>
/// <param name="hWnd">window message is for</param>
/// <param name="uMsg">message</param>
/// <param name="wParam">message data</param>
/// <param name="lParam">additional message data</param>
/// <returns>result of message processing</returns>
LRESULT CALLBACK CDataCollection::DlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int chour,cmin,csec;
	double dTimeInSeconds;
	WORD wDelayCharNum;
	TCHAR DelayTime[3];
	TCHAR ConstraintBuf[10];
	BROWSEINFO   bf;   
    LPITEMIDLIST   lpitem;   
	WCHAR comboItem[MAX_PATH];
//	WCHAR fileSavedMessage[50];

    switch (message)
    {
        case WM_INITDIALOG:
        {
			LOGFONT lf;
            // Bind application window handle
            m_hWnd = hWnd;

            // Init Direct2D
            D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory);

            // Create and initialize a new Direct2D image renderer (take a look at ImageRenderer.h)
            // We'll use this to draw the data we receive from the Kinect to the screen
            m_pDrawColor = new ImageRenderer();
			//m_pDrawDepth = new ImageRenderer();

            HRESULT hr = m_pDrawColor->Initialize(GetDlgItem(m_hWnd, IDC_COLOR), m_pD2DFactory, cColorWidth, cColorHeight, cColorWidth * sizeof(long));
            if (FAILED(hr))
            {
                SetStatusMessage(L"Failed to initialize the Direct2D draw device.");
            }

            // Look for a connected Kinect, and create it if found
            CreateFirstConnected();

			if(!SetCurrentDirectory(L"..\\output"))
				CreateDirectory(L"..\\output",NULL);
			
			//Set the font for recording time display
			GetObject( (HFONT) GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf );
			lf.lfHeight *= 3;
			SendDlgItemMessage( hWnd, IDC_SEC, WM_SETFONT, (WPARAM)CreateFontIndirect(&lf), 0 );
			SendDlgItemMessage( hWnd, IDC_MIN, WM_SETFONT, (WPARAM)CreateFontIndirect(&lf), 0 );
			SendDlgItemMessage( hWnd, IDC_HOUR, WM_SETFONT, (WPARAM)CreateFontIndirect(&lf), 0 );
			SendDlgItemMessage( hWnd, IDC_FRAME_SHOW, WM_SETFONT, (WPARAM)CreateFontIndirect(&lf), 0 );
			SendDlgItemMessage( hWnd, IDC_SEP, WM_SETFONT, (WPARAM)CreateFontIndirect(&lf), 0 );
			SendDlgItemMessage( hWnd, IDC_TIME_COUNT, WM_SETFONT, (WPARAM)CreateFontIndirect(&lf), 0 );

			SetWindowText(GetDlgItem(hWnd,IDC_DELAY),L"0");

			StringCchPrintfW(comboItem, _countof(comboItem), L"No constraints");
			SendDlgItemMessage(hWnd, IDC_MODE, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(comboItem));
			StringCchPrintfW(comboItem, _countof(comboItem), L"Time length(s)");
			SendDlgItemMessage(hWnd, IDC_MODE, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(comboItem));
			StringCchPrintfW(comboItem, _countof(comboItem), L"Frame number");
			SendDlgItemMessage(hWnd, IDC_MODE, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(comboItem));

			SendDlgItemMessage(hWnd, IDC_MODE, CB_SETCURSEL,0, 0);
			m_iRecordingModeIndex=DEFAULT_MODE;
			
		
			lastframetime=GetTickCount();
        }
        break;

        // If the titlebar X is clicked, destroy app
        case WM_CLOSE:
            DestroyWindow(hWnd);
            break;

        case WM_DESTROY:
            // Quit the main message pump
		
		
            PostQuitMessage(0);
            break;

        case WM_TIMER:                      //Handle timer message
			if(m_bSaveSkeStart){
			switch (wParam)  
			{  
			case TIMER_SEC:  
			
				currenttime=GetTickCount();
				dTimeInSeconds=(currenttime-starttime)/1000.0;
				csec=((currenttime-starttime)/1000)%60;
				cmin=((currenttime-starttime)/60000)%60;
				chour=((currenttime-starttime)/3600000)%24;
				::SetDlgItemInt(hWnd, static_cast<int>(IDC_SEC),csec, FALSE );
                ::SetDlgItemInt(hWnd, static_cast<int>(IDC_MIN),cmin, FALSE );
				::SetDlgItemInt(hWnd, static_cast<int>(IDC_HOUR),chour, FALSE );

				
				break ;  
		
			} 
			}
			else if (m_bIsInDelay){
				m_iDelayTime--;
				::SetDlgItemInt(hWnd, static_cast<int>(IDC_TIME_COUNT),m_iDelayTime, FALSE );
				if(m_iDelayTime==0)
				{
					//DEBUG("Start!\n");
					
				    USES_CONVERSION;
				    const char* ascName = T2A(skefname);
					
					m_pSkeData->SaveStart(ascName,m_iFrameConstraint,m_dwTimeConstraint);
					m_bIsInDelay = false;
					m_bSaveSkeStart = true;
					starttime = GetTickCount();
					
				}
				else{
					m_bIsInDelay = true;
				}
			}
			break;

        // Handle button press
        case WM_COMMAND:
            
			

			// If it was for the start control and a button clicked event, start saving the skeleton frame
			if(IDC_START== LOWORD(wParam) && BN_CLICKED == HIWORD(wParam))
			{
                TCHAR timeString[MAX_PATH];
				WORD wSavePathNum;
                
			    m_dwTimeConstraint = 0;
				m_iFrameConstraint = 0;
				
				GetTimeFormatEx(NULL,TIME_FORCE24HOURFORMAT, NULL, L"hh'-'mm'-'ss", timeString, _countof(timeString));
				wSavePathNum=(WORD) SendDlgItemMessage(hWnd,IDC_SAVE_PATH, EM_LINELENGTH, (WPARAM) 0, (LPARAM) 0);
				if(wSavePathNum==0)
				{
                    StringCchPrintfW(skefname, _countof(skefname), L"..\\output\\KinectSkeletonVideo-%s.skd",timeString);
				}
				else{
					StringCchPrintfW(skefname, _countof(skefname), L"%s\\KinectSkeletonVideo-%s.skd",m_SkeFilePath,timeString);
				}

				//hskf=CreateFile(skefname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
				//SetFilePointer(hskf,sizeof(SKEFILEHEADER)+sizeof(SKEINFORHEADER),NULL,FILE_CURRENT);
				wDelayCharNum=(WORD) SendDlgItemMessage(hWnd,IDC_DELAY, EM_LINELENGTH, (WPARAM) 0, (LPARAM) 0); 
				if (wDelayCharNum >= 3) 
				{ 
					MessageBox(hWnd, L"Too many characters!The number of characters should not be more than 3!", 
						L"Error", 
						MB_OK); 
					break;
				} 
				else if (wDelayCharNum == 0) 
				{ 
					MessageBox(hWnd, L"No characters entered.", 
						L"Error", 
						MB_OK);
					break;
				} 
				SendDlgItemMessage(hWnd,IDC_DELAY,EM_GETLINE, 
					(WPARAM) 0,       // line 0 
					(LPARAM) DelayTime);

				m_iDelayTime=::StrToInt(DelayTime);
				::SetDlgItemInt(hWnd, static_cast<int>(IDC_TIME_COUNT),m_iDelayTime, FALSE );
				

                SendDlgItemMessage(hWnd,IDC_CONSTRAINT,EM_GETLINE, 
						(WPARAM) 0,       // line 0 
						(LPARAM) ConstraintBuf);

				if(m_iRecordingModeIndex==TIME_MODE)
				{
					m_dwTimeConstraint=::StrToInt(ConstraintBuf);
				}
				else if(m_iRecordingModeIndex==FRAME_MODE)
				{
					m_iFrameConstraint=::StrToInt(ConstraintBuf);
				}

				::SetDlgItemInt(hWnd, static_cast<int>(IDC_SEC),0, FALSE );
				::SetDlgItemInt(hWnd, static_cast<int>(IDC_MIN),0, FALSE );
				::SetDlgItemInt(hWnd, static_cast<int>(IDC_HOUR),0, FALSE );
				::SetDlgItemInt(hWnd, static_cast<int>(IDC_FRAME_SHOW),0, FALSE );
				 
				if(m_iDelayTime==0)
				{
					//DEBUG("Start!\n");
					m_pSkeData->SaveStart((const char*)skefname,m_iFrameConstraint,m_dwTimeConstraint);
					m_bSaveSkeStart = true;
					

				} else {
				   
					m_bIsInDelay = true;
				}
				SetTimer (hWnd, TIMER_SEC, 1000, NULL) ;
			}

			// If it was for the stop control and a button clicked event, stop saving the skeleton frame
			if(IDC_STOP== LOWORD(wParam) && BN_CLICKED == HIWORD(wParam))
			{
				if(m_bSaveSkeStart)
				{
					KillTimer (hWnd, TIMER_SEC) ;
					m_bSaveSkeStart=false;
				    m_pSkeData->SaveEnd();
					//DEBUG("Stop!\n");
				}
				else if(m_bIsInDelay){
					KillTimer (hWnd, TIMER_SEC) ;
					::SetDlgItemInt(hWnd, static_cast<int>(IDC_TIME_COUNT),0, FALSE );
                   // CloseHandle(hskf);
					DeleteFile(skefname);
					
				}
				
					
			}

			if(IDC_BROWSE== LOWORD(wParam) && BN_CLICKED == HIWORD(wParam))
			{
				memset(&bf,0,sizeof(BROWSEINFO));   
                bf.hwndOwner=hWnd;   
                bf.lpszTitle=L"Choose the directory";   
                bf.ulFlags=BIF_RETURNONLYFSDIRS;    
                lpitem=SHBrowseForFolder(&bf);
				SHGetPathFromIDList(lpitem,m_SkeFilePath); 
				SetDlgItemText(hWnd,IDC_SAVE_PATH,m_SkeFilePath);
				

			}

			// If it was for the reset time control and a button clicked event, reset the time displayed to 0:0:0
			if(IDC_Reset== LOWORD(wParam) && BN_CLICKED == HIWORD(wParam))
			{
				::SetDlgItemInt(hWnd, static_cast<int>(IDC_SEC),0, FALSE );
				::SetDlgItemInt(hWnd, static_cast<int>(IDC_MIN),0, FALSE );
				::SetDlgItemInt(hWnd, static_cast<int>(IDC_HOUR),0, FALSE );
				::SetDlgItemInt(hWnd, static_cast<int>(IDC_FRAME_SHOW),0, FALSE );
			}

			// If there is a change of selection in the combobox
			if(HIWORD(wParam) == CBN_SELCHANGE)
			{
				 m_iRecordingModeIndex = SendMessage((HWND) lParam, (UINT) CB_GETCURSEL, 
					(WPARAM) 0, (LPARAM) 0);
				// DEBUG("Current mode:%d\n",m_iRecordingModeIndex);
				 if(m_iRecordingModeIndex==TIME_MODE)
				 {
					 SetWindowText(GetDlgItem(hWnd,IDC_CONSTRAINT),L"5");
				 }
				 else if(m_iRecordingModeIndex==FRAME_MODE)
				 {
					 SetWindowText(GetDlgItem(hWnd,IDC_CONSTRAINT),L"100");
				 }
				 else{
					 SetWindowText(GetDlgItem(hWnd,IDC_CONSTRAINT),L"");
				 }
			}
			
            break;
    }

    return FALSE;
}
Example #10
0
static void WINAPI _HandleEvent(_In_ PEVENT_RECORD per)
{
    if (!_s_fIsEnding)
    {
        PTRACE_EVENT_INFO ptei = nullptr;

        // Populate ptei.
        {
            DWORD cbEventInfo = 0;
            DWORD status = TdhGetEventInformation(per, 0, nullptr, nullptr, &cbEventInfo);
            if (ERROR_INSUFFICIENT_BUFFER == status)
            {
                ptei = (TRACE_EVENT_INFO*)malloc(cbEventInfo);
                if (ptei != nullptr)
                {
                    status = TdhGetEventInformation(per, 0, nullptr, ptei, &cbEventInfo);
                    if (status != ERROR_SUCCESS)
                    {
                        free(ptei);
                        ptei = nullptr;
                    }
                }
            }
        }

        // Timestamp
        {
            FILETIME ft;
            ft.dwHighDateTime = per->EventHeader.TimeStamp.HighPart;
            ft.dwLowDateTime = per->EventHeader.TimeStamp.LowPart;
            SYSTEMTIME st;
            FileTimeToSystemTime(&ft, &st);
            SystemTimeToTzSpecificLocalTime(nullptr, &st, &st);
            wchar_t wszDate[100];
            GetDateFormatEx(LOCALE_NAME_INVARIANT, NULL, &st, L"yyyyy-MM-dd", wszDate, ARRAYSIZE(wszDate), nullptr);
            wchar_t wszTime[100];
            GetTimeFormatEx(LOCALE_NAME_INVARIANT, NULL, &st, L"HH:mm:ss", wszTime, ARRAYSIZE(wszTime));

            // yyyy-MM-dd HH:mm:ss:fffffff
            // Windows refuses to give us milliseconds for free, let alone fractions of milliseconds
            wprintf(L"%s ", wszDate);
            wprintf(L"%s", wszTime);
            wprintf(L".%07u, ", ft.dwLowDateTime % ((1000000000 /*nanoseconds per second*/) / (100 /* nanoseconds per interval */)));
        }

        // Thread ID
        wprintf(L"Thread %lu, ", per->EventHeader.ThreadId);

        // Provider name or GUID
        {
            const wchar_t* providerName = ptei ? TEI_PROVIDER_NAME(ptei) : nullptr;
            if (providerName != nullptr)
            {
                wprintf(L"%s, ", (BYTE*)ptei + ptei->ProviderNameOffset);
            }
            else
            {
                BSTR bstrGuid;
                if (SUCCEEDED(StringFromCLSID(per->EventHeader.ProviderId, &bstrGuid)))
                {
                    wprintf(L"%s, ", bstrGuid);
                    ::CoTaskMemFree(bstrGuid);
                }
            }
        }

        // Task name or id
        {
            const wchar_t* taskName = ptei ? TEI_TASK_NAME(ptei) : nullptr;
            if (taskName != nullptr)
            {
                wprintf(L"%s, ", taskName);
            }
            else
            {
                // printf converts 8-bit chars to 16-bit ints, in case you don't know
                wprintf(L"%hu, ", per->EventHeader.EventDescriptor.Task);
            }
        }

        // Event ID
        // wprintf(L"%hu, ", per->EventHeader.EventDescriptor.Id);

        // Activity ID
        //{
        //    BSTR bstrGuid;
        //    if (SUCCEEDED(StringFromCLSID(per->EventHeader.ActivityId, &bstrGuid)))
        //    {
        //        wprintf(L"%s, ", bstrGuid);
        //        ::CoTaskMemFree(bstrGuid);
        //    }
        //}

        // Opcode name or ID
        {
            wchar_t* opcodeName = ptei ? TEI_OPCODE_NAME(ptei) : nullptr;
            if (opcodeName != nullptr)
            {
                wprintf(L"%s, ", (BYTE*)ptei + ptei->OpcodeNameOffset);
            }
            else
            {
                wprintf(L"%hu, ", per->EventHeader.EventDescriptor.Opcode);
            }
        }

        // Payload
        if (EVENT_HEADER_FLAG_STRING_ONLY == (per->EventHeader.Flags & EVENT_HEADER_FLAG_STRING_ONLY))
        {
            wprintf(L"%s", (LPWSTR)per->UserData);
        }
        else
        {
            for (USHORT i = 0; i < ptei->TopLevelPropertyCount; i++)
            {
                DWORD status = PrintProperties(per, ptei, i, nullptr, 0);
                if (ERROR_SUCCESS != status)
                {
                    wprintf(L"Printing top level properties failed.");
                }

                wprintf(L", ");
            }
        }

        // endl
        wprintf(L"\r\n");

        // combat stdout buffering
        _flushall();

        if (ptei != nullptr)
        {
            free(ptei);
            ptei = nullptr;
        }
    }
    else
    {
        if (!_s_fIsClosed)
        {
            CloseTrace(*((TRACEHANDLE*)per->UserContext));
            _s_fIsClosed = true;
        }
    }
}