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

498 lines
12 KiB

/*++
Copyright (C) 1999- Microsoft Corporation
Module Name:
ptputil.cpp
Abstract:
This module implements PTP data structure manipulating functions
Author:
William Hsieh (williamh) created
Revision History:
--*/
#include "ptppch.h"
//
// This function converts a PTP datetime string to Windows FILETIME.
//
// Input:
// pptpTime -- the PTP datetime string
// SystemTime -- SYSTEMTIME structure to receive the converted time
//
// Notes:
// PTP timestamp is a string with the format "YYYYMMDDThhmmss.s", where
// YYYY is the year
// MM is the month(1 - 12)
// DD is the day(1 - 31)
// T is the constant used to separate date and time
// hh is the hour(0 - 23)
// mm is the minute(0 - 59)
// ss is the second(0 - 59)
// .s is the optional 10th of second
//
// Append it with 'Z' means it is a UTC time.
// Append it with "+/-hhmm" means it is relative to a time zone.
// Append neither means the time zone is unknown, assume time zone of the host.
//
HRESULT
PtpTime2SystemTime(
CBstr *pptpTime,
SYSTEMTIME *pSystemTime
)
{
DBG_FN("PTPTime2FileTime");
HRESULT hr = S_OK;
if (!pSystemTime || !pptpTime || !pptpTime->String() ||
pptpTime->Length() < 4 + 2 + 2 + 1 + 2 + 2 + 2 ||
L'T' != pptpTime->String()[4 + 2 + 2])
{
wiauDbgTrace("PtpTime2SystemTime", "Invalid arg");
return E_INVALIDARG;
}
WCHAR TimeString[MAX_PATH];
ZeroMemory(TimeString, sizeof(TimeString));
hr = StringCchCopyW(TimeString, ARRAYSIZE(TimeString), pptpTime->String());
if (FAILED(hr))
{
wiauDbgErrorHr(hr, "PtpTime2SystemTime", "StringCchCopyW failed");
goto Cleanup;
}
WCHAR wch;
LPWSTR pwcsEnd;
wch = TimeString[4];
TimeString[4] = UNICODE_NULL;
pSystemTime->wYear = (WORD)wcstol(TimeString, &pwcsEnd, 10);
TimeString[4] = wch;
wch = TimeString[6];
TimeString[6] = UNICODE_NULL;
pSystemTime->wMonth = (WORD)wcstol(TimeString + 4, &pwcsEnd, 10);
TimeString[6] = wch;
wch = TimeString[8];
TimeString[8] = UNICODE_NULL;
pSystemTime->wDay = (WORD)wcstol(TimeString + 6 , &pwcsEnd, 10);
TimeString[8] = wch;
wch = TimeString[11];
TimeString[11] = UNICODE_NULL;
pSystemTime->wHour = (WORD)wcstol(TimeString + 9, &pwcsEnd, 10);
TimeString[11] = wch;
wch = TimeString[13];
TimeString[13] = UNICODE_NULL;
pSystemTime->wMinute = (WORD)wcstol(TimeString + 11, &pwcsEnd, 10);
TimeString[13] = wch;
wch = TimeString[15];
TimeString[15] = UNICODE_NULL;
pSystemTime->wSecond = (WORD)wcstol(TimeString + 13, &pwcsEnd, 10);
TimeString[15] = wch;
if (L'.' == wch)
{
wch = TimeString[17];
TimeString[17] = UNICODE_NULL;
pSystemTime->wMilliseconds = 100 * (WORD)wcstol(TimeString + 16, &pwcsEnd, 10);
TimeString[17] = wch;
}
else
{
pSystemTime->wMilliseconds = 0;
}
pSystemTime->wDayOfWeek = 0;
//
// WIAFIX-8/17/2000-davepar Time zone information is being ignored
//
Cleanup:
return hr;
}
//
// This function converts a SYSTEMTIME to PTP datetime string.
//
// Input:
// pSystemTime -- the SYSTEMTIME
// pptpTime -- target PTP datatime string
//
HRESULT
SystemTime2PtpTime(
SYSTEMTIME *pSystemTime,
CBstr *pptpTime,
BOOL bTwoDigitsForMilliseconds
)
{
DBG_FN("SystemTime2PTPTime");
HRESULT hr = S_OK;
if (!pptpTime || !pSystemTime)
{
wiauDbgError("SystemTime2PtpTime", "Invalid arg");
return E_INVALIDARG;
}
WCHAR ptpTimeStr[MAX_PATH];
WCHAR *pwstr;
pwstr = ptpTimeStr;
//
// Four digits for year, two for month, and two for day
//
swprintf(pwstr, L"%04d%02d%02d", pSystemTime->wYear, pSystemTime->wMonth, pSystemTime->wDay);
//
// Separator
//
pwstr[8] = L'T';
pwstr += 9;
//
// Two digits for hour, two for minute, and two for second
//
swprintf(pwstr, L"%02d%02d%02d", pSystemTime->wHour, pSystemTime->wMinute, pSystemTime->wSecond);
pwstr += 6;
//
// Optional tenth second
//
if (pSystemTime->wMilliseconds)
{
*pwstr++ = L'.';
//
// In XP, PTP driver was sending DATETIME string to camera with two digits for milliseconds (bug 699699)
// Some cameras may still expect this format. In this case, vendor should provide custom INF file for
// the camera and include the following string entry under DeviceData key:
//
// [ModelName.DeviceData]
// ...
// TwoDigitsMillisecondsOutput=1
// ...
//
if (bTwoDigitsForMilliseconds)
{
swprintf(pwstr, L"%02d", pSystemTime->wMilliseconds / 10);
pwstr += 2;
}
else
{
swprintf(pwstr, L"%01d", pSystemTime->wMilliseconds / 100);
pwstr += 1;
}
}
//
// NULL terminates the string
//
*pwstr = UNICODE_NULL;
hr = pptpTime->Copy(ptpTimeStr);
if (FAILED(hr))
{
wiauDbgError("SystemTime2PtpTime", "Copy failed");
return hr;
}
return hr;
}
//
// This function dumps a PTP command block to the log
//
// Input:
// pCommand -- pointer to a PTP command
// NumParams -- number of parameters in the command
//
VOID
DumpCommand(
PTP_COMMAND *pCommand,
DWORD NumParams
)
{
if (!pCommand)
{
wiauDbgError("DumpCommand", "Invalid arg");
return;
}
if (NumParams > COMMAND_NUMPARAMS_MAX)
{
NumParams = COMMAND_NUMPARAMS_MAX;
}
wiauDbgDump("DumpCommand", "Dumping command:");
wiauDbgDump("DumpCommand", " Opcode = 0x%04x", pCommand->OpCode);
wiauDbgDump("DumpCommand", " Session id = 0x%08x", pCommand->SessionId);
wiauDbgDump("DumpCommand", " Transaction id = 0x%08x", pCommand->TransactionId);
if (NumParams)
{
for (DWORD count = 0; count < NumParams; count++)
{
wiauDbgDump("DumpCommand", " Parameter %d = 0x%08x = %d",
count, pCommand->Params[count], pCommand->Params[count]);
}
}
}
//
// This function dumps a PTP response block to the log
//
// Input:
// pResponse -- pointer to a PTP response
//
VOID
DumpResponse(
PTP_RESPONSE *pResponse
)
{
if (!pResponse)
{
wiauDbgError("DumpResponse", "Invalid arg");
return;
}
wiauDbgDump("DumpResponse", "Dumping response:");
wiauDbgDump("DumpResponse", " Response code = 0x%04x", pResponse->ResponseCode);
wiauDbgDump("DumpResponse", " Session id = 0x%08x", pResponse->SessionId);
wiauDbgDump("DumpResponse", " Transaction id = 0x%08x", pResponse->TransactionId);
for (DWORD count = 0; count < RESPONSE_NUMPARAMS_MAX; count++)
{
wiauDbgDump("DumpResponse", " Parameter %d = 0x%08x = %d",
count, pResponse->Params[count], pResponse->Params[count]);
}
}
//
// This function dumps a PTP event block to the log
//
// Input:
// pEvent -- pointer to a PTP event
//
VOID
DumpEvent(
PTP_EVENT *pEvent
)
{
if (!pEvent)
{
wiauDbgError("DumpEvent", "Invalid arg");
return;
}
wiauDbgDump("DumpEvent", "Dumping event:");
wiauDbgDump("DumpEvent", " Event code = 0x%04x", pEvent->EventCode);
wiauDbgDump("DumpEvent", " Session id = 0x%08x", pEvent->SessionId);
wiauDbgDump("DumpEvent", " Transaction id = 0x%08x", pEvent->TransactionId);
for (DWORD count = 0; count < EVENT_NUMPARAMS_MAX; count++)
{
wiauDbgDump("DumpEvent", " Parameter %d = 0x%08x = %d",
count, pEvent->Params[count], pEvent->Params[count]);
}
}
//
// This function dumps a GUID to the log
//
// Input:
// pGuid -- GUID to dump
//
VOID
DumpGuid(
GUID *pGuid
)
{
HRESULT hr = S_OK;
if (!pGuid)
{
wiauDbgError("DumpGuid", "Invalid arg");
return;
}
WCHAR GuidStringW[128];
hr = StringFromGUID2(*pGuid, GuidStringW, sizeof(GuidStringW) / sizeof(WCHAR));
if (FAILED(hr))
{
wiauDbgError("DumpGuid", "StringFromGUID2 failed");
return;
}
wiauDbgDump("DumpGuid", "Guid = %S", GuidStringW);
return;
}
//
// This function opens a registry key
//
HRESULT
CPTPRegistry::Open(
HKEY hkAncestor,
LPCTSTR KeyName,
REGSAM Access
)
{
DBG_FN("CPTPRegistry::Open");
HRESULT hr = S_OK;
if (m_hKey)
{
wiauDbgError("Open", "Registry is already open");
return E_ACCESSDENIED;
}
DWORD Win32Err;
Win32Err = ::RegOpenKeyEx(hkAncestor, KeyName, 0, Access, &m_hKey);
if (Win32Err != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(Win32Err);
wiauDbgErrorHr(hr, "Open", "RegOpenKeyEx failed");
return hr;
}
return hr;
}
//
// This function gets a string type registry value
//
// Input:
// ValueName -- the value's name
// pptpStr -- the receive the value
//
HRESULT
CPTPRegistry::GetValueStr(
LPCTSTR ValueName,
TCHAR *string,
DWORD *pcbStringBytes
)
{
DBG_FN("CPTPRegistry::GetValueStr");
HRESULT hr = S_OK;
if (!ValueName || !string)
{
wiauDbgError("GetValueStr", "Invalid arg");
return E_INVALIDARG;
}
//
// Need to handle non-Unicode
//
DWORD Win32Err;
Win32Err = ::RegQueryValueEx(m_hKey, ValueName, NULL, NULL, (BYTE *) string, pcbStringBytes);
if (Win32Err != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(Win32Err);
wiauDbgErrorHr(hr, "GetValueStr", "RegQueryValueEx failed");
return hr;
}
return hr;
}
//
// This function gets a string type registry value and converts it to a DWORD
//
// Input:
// ValueName -- the value's name
// pptpStr -- the receive the value
//
HRESULT
CPTPRegistry::GetValueDword(
LPCTSTR ValueName,
DWORD *pValue
)
{
DBG_FN("CPTPRegistry::GetValueDword");
HRESULT hr = S_OK;
if (!ValueName || !pValue)
{
wiauDbgError("GetValueDword", "Invalid arg");
return E_INVALIDARG;
}
//
// Get the string from the registry
//
TCHAR string[MAX_PATH];
DWORD stringLen = sizeof(string);
hr = GetValueStr(ValueName, string, &stringLen);
if (FAILED(hr))
{
wiauDbgError("GetValueDword", "GetValueStr failed");
return hr;
}
*pValue = _tcstol(string, NULL, 0);
return hr;
}
//
// This function gets a list of codes registry value
//
// Input:
// ValueName -- the value's name
//
// pptpStr -- the receive the value
//
HRESULT
CPTPRegistry::GetValueCodes(
LPCTSTR ValueName,
CArray16 *pCodeArray
)
{
DBG_FN("CPTPRegistry::GetValueCodes");
HRESULT hr = S_OK;
if (!ValueName || !pCodeArray)
{
wiauDbgError("GetValueCodes", "Invalid arg");
return E_INVALIDARG;
}
//
// Get the string from the registry
//
TCHAR valueString[MAX_PATH];
DWORD stringLen = sizeof(valueString);
hr = GetValueStr(ValueName, valueString, &stringLen);
if (FAILED(hr))
{
wiauDbgError("GetValueCodes", "GetValueStr failed");
return hr;
}
//
// Parse the string for codes
//
TCHAR *pCurrent = _tcstok(valueString, TEXT(","));
WORD code;
while (pCurrent)
{
code = (WORD) _tcstol(pCurrent, NULL, 0);
pCodeArray->Add(code);
pCurrent = _tcstok(NULL, TEXT(","));
}
return hr;
}