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

  1. /*++
  2. Copyright (C) 1999- Microsoft Corporation
  3. Module Name:
  4. ptputil.cpp
  5. Abstract:
  6. This module implements PTP data structure manipulating functions
  7. Author:
  8. William Hsieh (williamh) created
  9. Revision History:
  10. --*/
  11. #include "ptppch.h"
  12. //
  13. // This function converts a PTP datetime string to Windows FILETIME.
  14. //
  15. // Input:
  16. // pptpTime -- the PTP datetime string
  17. // SystemTime -- SYSTEMTIME structure to receive the converted time
  18. //
  19. // Notes:
  20. // PTP timestamp is a string with the format "YYYYMMDDThhmmss.s", where
  21. // YYYY is the year
  22. // MM is the month(1 - 12)
  23. // DD is the day(1 - 31)
  24. // T is the constant used to separate date and time
  25. // hh is the hour(0 - 23)
  26. // mm is the minute(0 - 59)
  27. // ss is the second(0 - 59)
  28. // .s is the optional 10th of second
  29. //
  30. // Append it with 'Z' means it is a UTC time.
  31. // Append it with "+/-hhmm" means it is relative to a time zone.
  32. // Append neither means the time zone is unknown, assume time zone of the host.
  33. //
  34. HRESULT
  35. PtpTime2SystemTime(
  36. CBstr *pptpTime,
  37. SYSTEMTIME *pSystemTime
  38. )
  39. {
  40. DBG_FN("PTPTime2FileTime");
  41. HRESULT hr = S_OK;
  42. if (!pSystemTime || !pptpTime || !pptpTime->String() ||
  43. pptpTime->Length() < 4 + 2 + 2 + 1 + 2 + 2 + 2 ||
  44. L'T' != pptpTime->String()[4 + 2 + 2])
  45. {
  46. wiauDbgTrace("PtpTime2SystemTime", "Invalid arg");
  47. return E_INVALIDARG;
  48. }
  49. WCHAR TimeString[MAX_PATH];
  50. ZeroMemory(TimeString, sizeof(TimeString));
  51. hr = StringCchCopyW(TimeString, ARRAYSIZE(TimeString), pptpTime->String());
  52. if (FAILED(hr))
  53. {
  54. wiauDbgErrorHr(hr, "PtpTime2SystemTime", "StringCchCopyW failed");
  55. goto Cleanup;
  56. }
  57. WCHAR wch;
  58. LPWSTR pwcsEnd;
  59. wch = TimeString[4];
  60. TimeString[4] = UNICODE_NULL;
  61. pSystemTime->wYear = (WORD)wcstol(TimeString, &pwcsEnd, 10);
  62. TimeString[4] = wch;
  63. wch = TimeString[6];
  64. TimeString[6] = UNICODE_NULL;
  65. pSystemTime->wMonth = (WORD)wcstol(TimeString + 4, &pwcsEnd, 10);
  66. TimeString[6] = wch;
  67. wch = TimeString[8];
  68. TimeString[8] = UNICODE_NULL;
  69. pSystemTime->wDay = (WORD)wcstol(TimeString + 6 , &pwcsEnd, 10);
  70. TimeString[8] = wch;
  71. wch = TimeString[11];
  72. TimeString[11] = UNICODE_NULL;
  73. pSystemTime->wHour = (WORD)wcstol(TimeString + 9, &pwcsEnd, 10);
  74. TimeString[11] = wch;
  75. wch = TimeString[13];
  76. TimeString[13] = UNICODE_NULL;
  77. pSystemTime->wMinute = (WORD)wcstol(TimeString + 11, &pwcsEnd, 10);
  78. TimeString[13] = wch;
  79. wch = TimeString[15];
  80. TimeString[15] = UNICODE_NULL;
  81. pSystemTime->wSecond = (WORD)wcstol(TimeString + 13, &pwcsEnd, 10);
  82. TimeString[15] = wch;
  83. if (L'.' == wch)
  84. {
  85. wch = TimeString[17];
  86. TimeString[17] = UNICODE_NULL;
  87. pSystemTime->wMilliseconds = 100 * (WORD)wcstol(TimeString + 16, &pwcsEnd, 10);
  88. TimeString[17] = wch;
  89. }
  90. else
  91. {
  92. pSystemTime->wMilliseconds = 0;
  93. }
  94. pSystemTime->wDayOfWeek = 0;
  95. //
  96. // WIAFIX-8/17/2000-davepar Time zone information is being ignored
  97. //
  98. Cleanup:
  99. return hr;
  100. }
  101. //
  102. // This function converts a SYSTEMTIME to PTP datetime string.
  103. //
  104. // Input:
  105. // pSystemTime -- the SYSTEMTIME
  106. // pptpTime -- target PTP datatime string
  107. //
  108. HRESULT
  109. SystemTime2PtpTime(
  110. SYSTEMTIME *pSystemTime,
  111. CBstr *pptpTime,
  112. BOOL bTwoDigitsForMilliseconds
  113. )
  114. {
  115. DBG_FN("SystemTime2PTPTime");
  116. HRESULT hr = S_OK;
  117. if (!pptpTime || !pSystemTime)
  118. {
  119. wiauDbgError("SystemTime2PtpTime", "Invalid arg");
  120. return E_INVALIDARG;
  121. }
  122. WCHAR ptpTimeStr[MAX_PATH];
  123. WCHAR *pwstr;
  124. pwstr = ptpTimeStr;
  125. //
  126. // Four digits for year, two for month, and two for day
  127. //
  128. swprintf(pwstr, L"%04d%02d%02d", pSystemTime->wYear, pSystemTime->wMonth, pSystemTime->wDay);
  129. //
  130. // Separator
  131. //
  132. pwstr[8] = L'T';
  133. pwstr += 9;
  134. //
  135. // Two digits for hour, two for minute, and two for second
  136. //
  137. swprintf(pwstr, L"%02d%02d%02d", pSystemTime->wHour, pSystemTime->wMinute, pSystemTime->wSecond);
  138. pwstr += 6;
  139. //
  140. // Optional tenth second
  141. //
  142. if (pSystemTime->wMilliseconds)
  143. {
  144. *pwstr++ = L'.';
  145. //
  146. // In XP, PTP driver was sending DATETIME string to camera with two digits for milliseconds (bug 699699)
  147. // Some cameras may still expect this format. In this case, vendor should provide custom INF file for
  148. // the camera and include the following string entry under DeviceData key:
  149. //
  150. // [ModelName.DeviceData]
  151. // ...
  152. // TwoDigitsMillisecondsOutput=1
  153. // ...
  154. //
  155. if (bTwoDigitsForMilliseconds)
  156. {
  157. swprintf(pwstr, L"%02d", pSystemTime->wMilliseconds / 10);
  158. pwstr += 2;
  159. }
  160. else
  161. {
  162. swprintf(pwstr, L"%01d", pSystemTime->wMilliseconds / 100);
  163. pwstr += 1;
  164. }
  165. }
  166. //
  167. // NULL terminates the string
  168. //
  169. *pwstr = UNICODE_NULL;
  170. hr = pptpTime->Copy(ptpTimeStr);
  171. if (FAILED(hr))
  172. {
  173. wiauDbgError("SystemTime2PtpTime", "Copy failed");
  174. return hr;
  175. }
  176. return hr;
  177. }
  178. //
  179. // This function dumps a PTP command block to the log
  180. //
  181. // Input:
  182. // pCommand -- pointer to a PTP command
  183. // NumParams -- number of parameters in the command
  184. //
  185. VOID
  186. DumpCommand(
  187. PTP_COMMAND *pCommand,
  188. DWORD NumParams
  189. )
  190. {
  191. if (!pCommand)
  192. {
  193. wiauDbgError("DumpCommand", "Invalid arg");
  194. return;
  195. }
  196. if (NumParams > COMMAND_NUMPARAMS_MAX)
  197. {
  198. NumParams = COMMAND_NUMPARAMS_MAX;
  199. }
  200. wiauDbgDump("DumpCommand", "Dumping command:");
  201. wiauDbgDump("DumpCommand", " Opcode = 0x%04x", pCommand->OpCode);
  202. wiauDbgDump("DumpCommand", " Session id = 0x%08x", pCommand->SessionId);
  203. wiauDbgDump("DumpCommand", " Transaction id = 0x%08x", pCommand->TransactionId);
  204. if (NumParams)
  205. {
  206. for (DWORD count = 0; count < NumParams; count++)
  207. {
  208. wiauDbgDump("DumpCommand", " Parameter %d = 0x%08x = %d",
  209. count, pCommand->Params[count], pCommand->Params[count]);
  210. }
  211. }
  212. }
  213. //
  214. // This function dumps a PTP response block to the log
  215. //
  216. // Input:
  217. // pResponse -- pointer to a PTP response
  218. //
  219. VOID
  220. DumpResponse(
  221. PTP_RESPONSE *pResponse
  222. )
  223. {
  224. if (!pResponse)
  225. {
  226. wiauDbgError("DumpResponse", "Invalid arg");
  227. return;
  228. }
  229. wiauDbgDump("DumpResponse", "Dumping response:");
  230. wiauDbgDump("DumpResponse", " Response code = 0x%04x", pResponse->ResponseCode);
  231. wiauDbgDump("DumpResponse", " Session id = 0x%08x", pResponse->SessionId);
  232. wiauDbgDump("DumpResponse", " Transaction id = 0x%08x", pResponse->TransactionId);
  233. for (DWORD count = 0; count < RESPONSE_NUMPARAMS_MAX; count++)
  234. {
  235. wiauDbgDump("DumpResponse", " Parameter %d = 0x%08x = %d",
  236. count, pResponse->Params[count], pResponse->Params[count]);
  237. }
  238. }
  239. //
  240. // This function dumps a PTP event block to the log
  241. //
  242. // Input:
  243. // pEvent -- pointer to a PTP event
  244. //
  245. VOID
  246. DumpEvent(
  247. PTP_EVENT *pEvent
  248. )
  249. {
  250. if (!pEvent)
  251. {
  252. wiauDbgError("DumpEvent", "Invalid arg");
  253. return;
  254. }
  255. wiauDbgDump("DumpEvent", "Dumping event:");
  256. wiauDbgDump("DumpEvent", " Event code = 0x%04x", pEvent->EventCode);
  257. wiauDbgDump("DumpEvent", " Session id = 0x%08x", pEvent->SessionId);
  258. wiauDbgDump("DumpEvent", " Transaction id = 0x%08x", pEvent->TransactionId);
  259. for (DWORD count = 0; count < EVENT_NUMPARAMS_MAX; count++)
  260. {
  261. wiauDbgDump("DumpEvent", " Parameter %d = 0x%08x = %d",
  262. count, pEvent->Params[count], pEvent->Params[count]);
  263. }
  264. }
  265. //
  266. // This function dumps a GUID to the log
  267. //
  268. // Input:
  269. // pGuid -- GUID to dump
  270. //
  271. VOID
  272. DumpGuid(
  273. GUID *pGuid
  274. )
  275. {
  276. HRESULT hr = S_OK;
  277. if (!pGuid)
  278. {
  279. wiauDbgError("DumpGuid", "Invalid arg");
  280. return;
  281. }
  282. WCHAR GuidStringW[128];
  283. hr = StringFromGUID2(*pGuid, GuidStringW, sizeof(GuidStringW) / sizeof(WCHAR));
  284. if (FAILED(hr))
  285. {
  286. wiauDbgError("DumpGuid", "StringFromGUID2 failed");
  287. return;
  288. }
  289. wiauDbgDump("DumpGuid", "Guid = %S", GuidStringW);
  290. return;
  291. }
  292. //
  293. // This function opens a registry key
  294. //
  295. HRESULT
  296. CPTPRegistry::Open(
  297. HKEY hkAncestor,
  298. LPCTSTR KeyName,
  299. REGSAM Access
  300. )
  301. {
  302. DBG_FN("CPTPRegistry::Open");
  303. HRESULT hr = S_OK;
  304. if (m_hKey)
  305. {
  306. wiauDbgError("Open", "Registry is already open");
  307. return E_ACCESSDENIED;
  308. }
  309. DWORD Win32Err;
  310. Win32Err = ::RegOpenKeyEx(hkAncestor, KeyName, 0, Access, &m_hKey);
  311. if (Win32Err != ERROR_SUCCESS)
  312. {
  313. hr = HRESULT_FROM_WIN32(Win32Err);
  314. wiauDbgErrorHr(hr, "Open", "RegOpenKeyEx failed");
  315. return hr;
  316. }
  317. return hr;
  318. }
  319. //
  320. // This function gets a string type registry value
  321. //
  322. // Input:
  323. // ValueName -- the value's name
  324. // pptpStr -- the receive the value
  325. //
  326. HRESULT
  327. CPTPRegistry::GetValueStr(
  328. LPCTSTR ValueName,
  329. TCHAR *string,
  330. DWORD *pcbStringBytes
  331. )
  332. {
  333. DBG_FN("CPTPRegistry::GetValueStr");
  334. HRESULT hr = S_OK;
  335. if (!ValueName || !string)
  336. {
  337. wiauDbgError("GetValueStr", "Invalid arg");
  338. return E_INVALIDARG;
  339. }
  340. //
  341. // Need to handle non-Unicode
  342. //
  343. DWORD Win32Err;
  344. Win32Err = ::RegQueryValueEx(m_hKey, ValueName, NULL, NULL, (BYTE *) string, pcbStringBytes);
  345. if (Win32Err != ERROR_SUCCESS)
  346. {
  347. hr = HRESULT_FROM_WIN32(Win32Err);
  348. wiauDbgErrorHr(hr, "GetValueStr", "RegQueryValueEx failed");
  349. return hr;
  350. }
  351. return hr;
  352. }
  353. //
  354. // This function gets a string type registry value and converts it to a DWORD
  355. //
  356. // Input:
  357. // ValueName -- the value's name
  358. // pptpStr -- the receive the value
  359. //
  360. HRESULT
  361. CPTPRegistry::GetValueDword(
  362. LPCTSTR ValueName,
  363. DWORD *pValue
  364. )
  365. {
  366. DBG_FN("CPTPRegistry::GetValueDword");
  367. HRESULT hr = S_OK;
  368. if (!ValueName || !pValue)
  369. {
  370. wiauDbgError("GetValueDword", "Invalid arg");
  371. return E_INVALIDARG;
  372. }
  373. //
  374. // Get the string from the registry
  375. //
  376. TCHAR string[MAX_PATH];
  377. DWORD stringLen = sizeof(string);
  378. hr = GetValueStr(ValueName, string, &stringLen);
  379. if (FAILED(hr))
  380. {
  381. wiauDbgError("GetValueDword", "GetValueStr failed");
  382. return hr;
  383. }
  384. *pValue = _tcstol(string, NULL, 0);
  385. return hr;
  386. }
  387. //
  388. // This function gets a list of codes registry value
  389. //
  390. // Input:
  391. // ValueName -- the value's name
  392. //
  393. // pptpStr -- the receive the value
  394. //
  395. HRESULT
  396. CPTPRegistry::GetValueCodes(
  397. LPCTSTR ValueName,
  398. CArray16 *pCodeArray
  399. )
  400. {
  401. DBG_FN("CPTPRegistry::GetValueCodes");
  402. HRESULT hr = S_OK;
  403. if (!ValueName || !pCodeArray)
  404. {
  405. wiauDbgError("GetValueCodes", "Invalid arg");
  406. return E_INVALIDARG;
  407. }
  408. //
  409. // Get the string from the registry
  410. //
  411. TCHAR valueString[MAX_PATH];
  412. DWORD stringLen = sizeof(valueString);
  413. hr = GetValueStr(ValueName, valueString, &stringLen);
  414. if (FAILED(hr))
  415. {
  416. wiauDbgError("GetValueCodes", "GetValueStr failed");
  417. return hr;
  418. }
  419. //
  420. // Parse the string for codes
  421. //
  422. TCHAR *pCurrent = _tcstok(valueString, TEXT(","));
  423. WORD code;
  424. while (pCurrent)
  425. {
  426. code = (WORD) _tcstol(pCurrent, NULL, 0);
  427. pCodeArray->Add(code);
  428. pCurrent = _tcstok(NULL, TEXT(","));
  429. }
  430. return hr;
  431. }