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.

734 lines
23 KiB

  1. //--------------------------------------------------------------------
  2. // HWProv.cpp - sample code
  3. // Copyright (C) Microsoft Corporation, 2001
  4. //
  5. // Created by: Duncan Bryce (duncanb), 9-13-2001
  6. //
  7. // A sample hardware provider
  8. //
  9. #include "pch.h"
  10. //
  11. // This provider will read from hardware clocks which can be configured purely
  12. // through serial port parametners. The clocks must periodically push data
  13. // onto the serial cable, in a format specified by the "Format" reg value
  14. // Furthermore, we will only accept input using ASCII character values.
  15. //
  16. // TODO: unicode support?
  17. // need polling character?
  18. // verify which clocks we work with
  19. // dynamically allocate format string based on calculated length?
  20. // why is 32seconds the irregular interval??
  21. // ensure that w32time calls into providers in a single-threaded fashion
  22. // should support placement of "time marker"?
  23. //
  24. struct HWProvState {
  25. TimeProvSysCallbacks tpsc;
  26. // Configuration information
  27. DCB dcb;
  28. HANDLE hComPort;
  29. WCHAR *wszCommPort;
  30. char cSampleInputBuffer[256]; // BUGBUG: add assert to ensure we cant overrun this buffer
  31. WCHAR *wszRefID;
  32. // Parser information
  33. HANDLE hParser;
  34. WCHAR *wszFormat;
  35. DWORD dwSampleSize;
  36. // Synchronization
  37. HANDLE hStopEvent;
  38. HANDLE hProvThread_EnterOrLeaveThreadTrapEvent;
  39. HANDLE hProvThread_ThreadTrapTransitionCompleteEvent;
  40. HANDLE hProvThread;
  41. CRITICAL_SECTION csProv;
  42. bool bIsCsProvInitialized;
  43. // Time sample information
  44. bool bSampleIsValid;
  45. NtTimeEpoch teSampleReceived;
  46. TimeSample tsCurrent;
  47. };
  48. struct HWProvConfig {
  49. DWORD dwBaudRate; //
  50. DWORD dwByteSize; //
  51. DWORD dwParity; // 0-4=no,odd,even,mark,space
  52. DWORD dwStopBits; //
  53. WCHAR *wszCommPort; //
  54. WCHAR *wszFormat; //
  55. WCHAR *wszRefID; //
  56. };
  57. HWProvState *g_phpstate = NULL;
  58. void __cdecl SeTransFunc(unsigned int u, EXCEPTION_POINTERS* pExp) {
  59. throw SeException(u);
  60. }
  61. HRESULT TrapThreads(bool bEnter) {
  62. DWORD dwWaitResult;
  63. HRESULT hr;
  64. // BUGBUG: need critsec to serialize TrapThreads?
  65. // BUGBUG: should the trap threads events be manual?
  66. // if auto, we'll try only once, but code simpler/
  67. // if manual, we'll keep trying on failure, but might be expensive!
  68. if (!SetEvent(g_phpstate->hProvThread_EnterOrLeaveThreadTrapEvent)) {
  69. _JumpLastError(hr, error, "SetEvent");
  70. }
  71. dwWaitResult = WaitForSingleObject(g_phpstate->hProvThread_ThreadTrapTransitionCompleteEvent, INFINITE);
  72. if (WAIT_FAILED == dwWaitResult) {
  73. _JumpLastError(hr, error, "WaitForSingleObject");
  74. }
  75. hr = S_OK;
  76. error:
  77. return hr;
  78. }
  79. HRESULT ThreadTrap() {
  80. DWORD dwWaitResult;
  81. HRESULT hr;
  82. if (!SetEvent(g_phpstate->hProvThread_ThreadTrapTransitionCompleteEvent)) {
  83. _JumpLastError(hr, error, "SetEvent");
  84. }
  85. dwWaitResult = WaitForSingleObject(g_phpstate->hProvThread_EnterOrLeaveThreadTrapEvent, INFINITE);
  86. if (WAIT_FAILED == dwWaitResult) {
  87. _JumpLastError(hr, error, "WaitForSingleObject");
  88. }
  89. if (!SetEvent(g_phpstate->hProvThread_ThreadTrapTransitionCompleteEvent)) {
  90. _JumpLastError(hr, error, "SetEvent");
  91. }
  92. hr = S_OK;
  93. error:
  94. return hr;
  95. }
  96. //--------------------------------------------------------------------
  97. VOID CALLBACK HandleDataAvail(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, OVERLAPPED *po) {
  98. bool bEnteredCriticalSection = false;
  99. HRESULT hr;
  100. unsigned __int64 nSysCurrentTime;
  101. unsigned __int64 nSysPhaseOffset;
  102. unsigned __int64 nSysTickCount;
  103. // Parse the returned data based on the format string:
  104. if (ERROR_SUCCESS != dwErrorCode) {
  105. hr = HRESULT_FROM_WIN32(dwErrorCode);
  106. _JumpError(hr, error, "HandleDataAvail: ReadFileEx failed");
  107. }
  108. // Get the required timestamp information:
  109. hr = g_phpstate->tpsc.pfnGetTimeSysInfo(TSI_CurrentTime, &nSysCurrentTime);
  110. _JumpIfError(hr, error, "g_phpstate->tpsc.pfnGetTimeSysInfo");
  111. hr = g_phpstate->tpsc.pfnGetTimeSysInfo(TSI_TickCount, &nSysTickCount);
  112. _JumpIfError(hr, error, "g_pnpstate->tpsc.pfnGetTimeSysInfo");
  113. hr = g_phpstate->tpsc.pfnGetTimeSysInfo(TSI_PhaseOffset, &nSysPhaseOffset);
  114. _JumpIfError(hr, error, "g_pnpstate->tpsc.pfnGetTimeSysInfo");
  115. _EnterCriticalSectionOrFail(&g_phpstate->csProv, bEnteredCriticalSection, hr, error);
  116. // Convert the data retrieved from the time hardware into a time sample:
  117. hr = ParseSample(g_phpstate->hParser, g_phpstate->cSampleInputBuffer, nSysCurrentTime, nSysPhaseOffset, nSysTickCount, &g_phpstate->tsCurrent);
  118. _JumpIfError(hr, error, "ParseFormatString");
  119. // Indicate that we now have a valid sample
  120. g_phpstate->bSampleIsValid = true;
  121. hr = g_phpstate->tpsc.pfnAlertSamplesAvail();
  122. _JumpIfError(hr, error, "g_pnpstate->tpsc.pfnAlertSamplesAvail");
  123. hr = S_OK;
  124. error:;
  125. _LeaveCriticalSection(&g_phpstate->csProv, bEnteredCriticalSection, hr);
  126. // BUGBUG: do we want to sleep on error?
  127. // return hr;
  128. }
  129. //--------------------------------------------------------------------
  130. MODULEPRIVATE DWORD WINAPI HwProvThread(void * pvIgnored) {
  131. DWORD dwLength;
  132. DWORD dwWaitResult;
  133. HRESULT hr;
  134. OVERLAPPED o;
  135. HANDLE rghWait[] = {
  136. g_phpstate->hStopEvent,
  137. g_phpstate->hProvThread_EnterOrLeaveThreadTrapEvent
  138. };
  139. ZeroMemory(&o, sizeof(o));
  140. if (!ReadFileEx(g_phpstate->hComPort, g_phpstate->cSampleInputBuffer, g_phpstate->dwSampleSize, &o, HandleDataAvail)) {
  141. _JumpLastError(hr, error, "ReadFileEx");
  142. }
  143. while (true) {
  144. dwWaitResult = WaitForMultipleObjectsEx(ARRAYSIZE(rghWait), rghWait, FALSE, INFINITE, TRUE);
  145. if (WAIT_OBJECT_0 == dwWaitResult) {
  146. // stop event
  147. goto done;
  148. } else if (WAIT_OBJECT_0+1 == dwWaitResult) {
  149. // thread trap notification. Trap this thread:
  150. hr = ThreadTrap();
  151. _JumpIfError(hr, error, "ThreadTrap");
  152. } else if (WAIT_IO_COMPLETION == dwWaitResult) {
  153. // we read some data. Queue up another read.
  154. ZeroMemory(&o, sizeof(o));
  155. ZeroMemory(g_phpstate->cSampleInputBuffer, sizeof(g_phpstate->cSampleInputBuffer));
  156. if (!ReadFileEx(g_phpstate->hComPort, g_phpstate->cSampleInputBuffer, g_phpstate->dwSampleSize, &o, HandleDataAvail)) {
  157. _JumpLastError(hr, error, "ReadFileEx");
  158. }
  159. } else {
  160. /*failed*/
  161. _JumpLastError(hr, error, "WaitForMultipleObjects");
  162. }
  163. }
  164. done:
  165. hr = S_OK;
  166. error:
  167. // BUGBUG: is CancelIo called implicitly?
  168. return hr;
  169. }
  170. //--------------------------------------------------------------------
  171. HRESULT StopHwProv() {
  172. DWORD dwWaitResult;
  173. HRESULT hr = S_OK;
  174. if (NULL != g_phpstate) {
  175. // Shut down the HW prov thread:
  176. if (NULL != g_phpstate->hStopEvent) {
  177. SetEvent(g_phpstate->hStopEvent);
  178. }
  179. dwWaitResult = WaitForSingleObject(g_phpstate->hProvThread, INFINITE);
  180. if (WAIT_FAILED == dwWaitResult) {
  181. _IgnoreLastError("WaitForSingleObject");
  182. }
  183. if (!GetExitCodeThread(g_phpstate->hProvThread, (DWORD *)&hr)) {
  184. _IgnoreLastError("GetExitCodeThread");
  185. } else if (FAILED(hr)) {
  186. _IgnoreError(hr, "(HwProvThread)");
  187. }
  188. CloseHandle(g_phpstate->hProvThread);
  189. if (NULL != g_phpstate->hStopEvent) {
  190. CloseHandle(g_phpstate->hStopEvent);
  191. }
  192. if (NULL != g_phpstate->hProvThread_EnterOrLeaveThreadTrapEvent) {
  193. CloseHandle(g_phpstate->hProvThread_EnterOrLeaveThreadTrapEvent);
  194. }
  195. if (NULL != g_phpstate->hProvThread_ThreadTrapTransitionCompleteEvent) {
  196. CloseHandle(g_phpstate->hProvThread_ThreadTrapTransitionCompleteEvent);
  197. }
  198. if (NULL != g_phpstate->hComPort && INVALID_HANDLE_VALUE != g_phpstate->hComPort) {
  199. CloseHandle(g_phpstate->hComPort);
  200. }
  201. if (NULL != g_phpstate->wszCommPort) {
  202. LocalFree(g_phpstate->wszCommPort);
  203. }
  204. if (NULL != g_phpstate->wszFormat) {
  205. LocalFree(g_phpstate->wszFormat);
  206. }
  207. if (NULL != g_phpstate->hParser) {
  208. FreeParser(g_phpstate->hParser);
  209. }
  210. if (g_phpstate->bIsCsProvInitialized) {
  211. DeleteCriticalSection(&g_phpstate->csProv);
  212. g_phpstate->bIsCsProvInitialized = false;
  213. }
  214. LocalFree(g_phpstate);
  215. ZeroMemory(g_phpstate, sizeof(HWProvState));
  216. }
  217. return hr;
  218. }
  219. //--------------------------------------------------------------------
  220. void FreeHwProvConfig(HWProvConfig *phwpConfig) {
  221. if (NULL != phwpConfig) {
  222. if (NULL != phwpConfig->wszCommPort) {
  223. LocalFree(phwpConfig->wszCommPort);
  224. }
  225. if (NULL != phwpConfig->wszFormat) {
  226. LocalFree(phwpConfig->wszFormat);
  227. }
  228. if (NULL != phwpConfig->wszRefID) {
  229. LocalFree(phwpConfig->wszRefID);
  230. }
  231. LocalFree(phwpConfig);
  232. }
  233. }
  234. //--------------------------------------------------------------------
  235. HRESULT ReadHwProvConfig(HWProvConfig **pphwpConfig) {
  236. DWORD dwResult;
  237. HKEY hkConfig = NULL;
  238. HRESULT hr;
  239. HWProvConfig *phwpConfig = NULL;
  240. WCHAR wszBuf[256];
  241. dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, wszHwProvRegKeyConfig, 0, KEY_READ, &hkConfig);
  242. if (ERROR_SUCCESS != dwResult) {
  243. hr=HRESULT_FROM_WIN32(dwResult);
  244. _JumpErrorStr(hr, error, "RegOpenKeyEx", wszHwProvRegKeyConfig);
  245. }
  246. phwpConfig = (HWProvConfig *)LocalAlloc(LPTR, sizeof(HWProvConfig));
  247. _JumpIfOutOfMemory(hr, error, phwpConfig);
  248. struct {
  249. WCHAR *wszRegValue;
  250. DWORD *pdwValue;
  251. } rgRegParams[] = {
  252. {
  253. wszHwProvRegValueBaudRate,
  254. &phwpConfig->dwBaudRate
  255. }, {
  256. wszHwProvRegValueByteSize,
  257. &phwpConfig->dwByteSize
  258. }, {
  259. wszHwProvRegValueParity,
  260. &phwpConfig->dwParity
  261. }, {
  262. wszHwProvRegValueStopBits,
  263. &phwpConfig->dwStopBits
  264. }
  265. };
  266. for (DWORD dwIndex = 0; dwIndex < ARRAYSIZE(rgRegParams); dwIndex++) {
  267. DWORD dwSize = sizeof(DWORD);
  268. DWORD dwType;
  269. dwResult = RegQueryValueEx(hkConfig, rgRegParams[dwIndex].wszRegValue, NULL, &dwType, (BYTE *)rgRegParams[dwIndex].pdwValue, &dwSize);
  270. if (ERROR_SUCCESS != dwResult) {
  271. hr = HRESULT_FROM_WIN32(GetLastError());
  272. _JumpErrorStr(hr, error, "RegQueryValue", rgRegParams[dwIndex].wszRegValue);
  273. }
  274. _Verify(REG_DWORD == dwType, hr, error);
  275. }
  276. struct {
  277. WCHAR *wszRegValue;
  278. WCHAR **ppwszValue;
  279. } rgRegSzParams[] = {
  280. {
  281. wszHwProvRegValueComPort,
  282. &phwpConfig->wszCommPort
  283. }, {
  284. wszHwProvRegValueFormat,
  285. &phwpConfig->wszFormat
  286. }, {
  287. wszHwProvRegValueRefID,
  288. &phwpConfig->wszRefID
  289. }
  290. };
  291. for (DWORD dwIndex = 0; dwIndex < ARRAYSIZE(rgRegSzParams); dwIndex++) {
  292. DWORD dwSize = sizeof(wszBuf);
  293. DWORD dwType;
  294. dwResult = RegQueryValueEx(hkConfig, rgRegSzParams[dwIndex].wszRegValue, NULL, &dwType, (BYTE *)wszBuf, &dwSize);
  295. if (ERROR_SUCCESS != dwResult) {
  296. hr = HRESULT_FROM_WIN32(dwResult);
  297. _JumpErrorStr(hr, error, "RegQueryValueEx", rgRegSzParams[dwIndex].wszRegValue);
  298. }
  299. _Verify(REG_SZ == dwType, hr, error);
  300. *(rgRegSzParams[dwIndex].ppwszValue) = (WCHAR *)LocalAlloc(LPTR, dwSize);
  301. _JumpIfOutOfMemory(hr, error, *(rgRegSzParams[dwIndex].ppwszValue));
  302. wcscpy(*(rgRegSzParams[dwIndex].ppwszValue), wszBuf);
  303. }
  304. *pphwpConfig = phwpConfig;
  305. phwpConfig = NULL;
  306. hr = S_OK;
  307. error:
  308. if (NULL != hkConfig) {
  309. RegCloseKey(hkConfig);
  310. }
  311. if (NULL != phwpConfig) {
  312. FreeHwProvConfig(phwpConfig);
  313. }
  314. return hr;
  315. }
  316. //--------------------------------------------------------------------
  317. HRESULT HandleUpdateConfig(void) {
  318. bool bComConfigUpdated = false;
  319. bool bTrappedThreads = false;
  320. HRESULT hr;
  321. HWProvConfig *phwpConfig = NULL;
  322. hr = TrapThreads(true);
  323. _JumpIfError(hr, error, "TrapThreads");
  324. bTrappedThreads = true;
  325. hr = ReadHwProvConfig(&phwpConfig);
  326. _JumpIfError(hr, error, "ReadHwProvConfig");
  327. // BUGBUG: need to update when com config changes!!
  328. //
  329. if (g_phpstate->dcb.BaudRate != phwpConfig->dwBaudRate) {
  330. g_phpstate->dcb.BaudRate = phwpConfig->dwBaudRate;
  331. bComConfigUpdated = true;
  332. }
  333. if (g_phpstate->dcb.ByteSize != (BYTE)phwpConfig->dwByteSize) {
  334. g_phpstate->dcb.ByteSize = (BYTE)phwpConfig->dwByteSize;
  335. bComConfigUpdated = true;
  336. }
  337. if (g_phpstate->dcb.Parity != (BYTE)phwpConfig->dwParity) {
  338. g_phpstate->dcb.Parity = (BYTE)phwpConfig->dwParity;
  339. bComConfigUpdated = true;
  340. }
  341. if (g_phpstate->dcb.StopBits != (BYTE)phwpConfig->dwStopBits) {
  342. g_phpstate->dcb.StopBits = (BYTE)phwpConfig->dwStopBits;
  343. bComConfigUpdated = true;
  344. }
  345. if (0 != wcscmp(g_phpstate->wszFormat, phwpConfig->wszFormat)) {
  346. LocalFree(g_phpstate->wszFormat);
  347. g_phpstate->wszFormat = phwpConfig->wszFormat;
  348. phwpConfig->wszFormat = NULL;
  349. FreeParser(g_phpstate->hParser);
  350. g_phpstate->hParser = NULL;
  351. hr = MakeParser(g_phpstate->wszFormat, &g_phpstate->hParser);
  352. _JumpIfError(hr, error, "MakeParser");
  353. g_phpstate->dwSampleSize = GetSampleSize(g_phpstate->hParser);
  354. }
  355. if (bComConfigUpdated) {
  356. if (!SetCommState(g_phpstate->hComPort, &g_phpstate->dcb)) {
  357. _JumpLastError(hr, error, "SetCommState");
  358. }
  359. // BUGBUG: PurgeComm()?
  360. }
  361. hr = S_OK;
  362. error:
  363. if (bTrappedThreads) {
  364. HRESULT hr2 = TrapThreads(false);
  365. _TeardownError(hr, hr2, "TrapThreads");
  366. }
  367. if (NULL != phwpConfig) {
  368. FreeHwProvConfig(phwpConfig);
  369. }
  370. if (FAILED(hr)) {
  371. HRESULT hr2 = StopHwProv();
  372. _IgnoreIfError(hr2, "StopHwProv");
  373. }
  374. return hr;
  375. }
  376. //--------------------------------------------------------------------
  377. MODULEPRIVATE HRESULT HandleTimeJump(TpcTimeJumpedArgs *ptjArgs) {
  378. bool bEnteredCriticalSection = false;
  379. HRESULT hr;
  380. _EnterCriticalSectionOrFail(&g_phpstate->csProv, bEnteredCriticalSection, hr, error);
  381. g_phpstate->bSampleIsValid = false;
  382. hr = S_OK;
  383. error:
  384. _LeaveCriticalSection(&g_phpstate->csProv, bEnteredCriticalSection, hr);
  385. return hr;
  386. }
  387. //--------------------------------------------------------------------
  388. HRESULT HandleGetSamples(TpcGetSamplesArgs * ptgsa) {
  389. bool bEnteredCriticalSection = false;
  390. DWORD dwBytesRemaining;
  391. HRESULT hr;
  392. TimeSample *pts = NULL;
  393. pts = (TimeSample *)ptgsa->pbSampleBuf;
  394. dwBytesRemaining = ptgsa->cbSampleBuf;
  395. ptgsa->dwSamplesAvailable = 0;
  396. ptgsa->dwSamplesReturned = 0;
  397. _EnterCriticalSectionOrFail(&g_phpstate->csProv, bEnteredCriticalSection, hr, error);
  398. if (g_phpstate->bSampleIsValid) {
  399. ptgsa->dwSamplesAvailable++;
  400. if (dwBytesRemaining < sizeof(TimeSample)) {
  401. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  402. _JumpError(hr, error, "HandleGetSamples: filling in sample buffer");
  403. }
  404. // Copy our current time sample over to the output buffer:
  405. memcpy(pts, &g_phpstate->tsCurrent, sizeof(TimeSample));
  406. ptgsa->dwSamplesReturned++;
  407. // calculate the dispersion - add skew dispersion due to time
  408. // since the sample's dispersion was last updated, and clamp to max dispersion.
  409. NtTimePeriod tpDispersionTemp;
  410. NtTimeEpoch teNow;
  411. hr = g_phpstate->tpsc.pfnGetTimeSysInfo(TSI_CurrentTime, &teNow.qw);
  412. _JumpIfError(hr, error, "g_phpstate->tpsc.pfnGetTimeSysInfo");
  413. // see how long it's been since we received the sample:
  414. if (teNow > g_phpstate->teSampleReceived) {
  415. tpDispersionTemp = abs(teNow - g_phpstate->teSampleReceived);
  416. tpDispersionTemp = NtpConst::timesMaxSkewRate(tpDispersionTemp);
  417. }
  418. tpDispersionTemp.qw += g_phpstate->tsCurrent.tpDispersion;
  419. if (tpDispersionTemp > NtpConst::tpMaxDispersion) {
  420. tpDispersionTemp = NtpConst::tpMaxDispersion;
  421. }
  422. pts->tpDispersion = tpDispersionTemp.qw;
  423. }
  424. hr = S_OK;
  425. error:
  426. _LeaveCriticalSection(&g_phpstate->csProv, bEnteredCriticalSection, hr);
  427. return hr;
  428. }
  429. //--------------------------------------------------------------------
  430. HRESULT StartHwProv(TimeProvSysCallbacks * pSysCallbacks) {
  431. DWORD dwThreadID;
  432. HRESULT hr;
  433. HWProvConfig *phpc = NULL;
  434. g_phpstate = (HWProvState *)LocalAlloc(LPTR, sizeof(HWProvState));
  435. _JumpIfOutOfMemory(hr, error, g_phpstate);
  436. hr = myInitializeCriticalSection(&g_phpstate->csProv);
  437. _JumpIfError(hr, error, "myInitializeCriticalSection");
  438. g_phpstate->bIsCsProvInitialized = true;
  439. // save the callbacks table
  440. if (sizeof(g_phpstate->tpsc) != pSysCallbacks->dwSize) {
  441. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  442. _JumpIfError(hr, error, "StartHwProv: save the callbacks table");
  443. }
  444. memcpy(&g_phpstate->tpsc, pSysCallbacks, sizeof(g_phpstate->tpsc));
  445. // read the configuration
  446. hr = ReadHwProvConfig(&phpc);
  447. _JumpIfError(hr, error, "ReadHwProvConfig");
  448. // Copy over the string config info:
  449. g_phpstate->wszCommPort = phpc->wszCommPort;
  450. phpc->wszCommPort = NULL; // prevent wszCommPort from being double-freed
  451. g_phpstate->wszFormat = phpc->wszFormat;
  452. phpc->wszFormat = NULL; // prevent wszFormat from being double-freed
  453. g_phpstate->wszRefID = phpc->wszRefID;
  454. phpc->wszRefID = NULL; // prevent wszRefID from being double-freed
  455. // Create a parser from the specified format string:
  456. hr = MakeParser(g_phpstate->wszFormat, &g_phpstate->hParser);
  457. _JumpIfError(hr, error, "MakeParser");
  458. g_phpstate->dwSampleSize = GetSampleSize(g_phpstate->hParser);
  459. // The remaining info are comm configuration, which we'll add to the
  460. // current comm configuration. Open the comm port so we can get the
  461. // comm state.
  462. g_phpstate->hComPort = CreateFile(g_phpstate->wszCommPort, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
  463. if (INVALID_HANDLE_VALUE == g_phpstate->hComPort || NULL == g_phpstate->hComPort) {
  464. _JumpLastError(hr, error, "CreateFile");
  465. }
  466. // Set the Comm state based on
  467. // a) the existing Comm state
  468. // and b) Comm config found in the registry
  469. if (!GetCommState(g_phpstate->hComPort, &g_phpstate->dcb)) {
  470. _JumpLastError(hr, error, "GetCommState");
  471. }
  472. g_phpstate->dcb.BaudRate = phpc->dwBaudRate;
  473. g_phpstate->dcb.ByteSize = (BYTE)phpc->dwByteSize;
  474. g_phpstate->dcb.Parity = (BYTE)phpc->dwParity;
  475. g_phpstate->dcb.StopBits = (BYTE)phpc->dwStopBits;
  476. // BUGBUG: pulled these values from timeserv.c. Need to document
  477. // why they work??
  478. g_phpstate->dcb.fOutxCtsFlow = FALSE;
  479. g_phpstate->dcb.fDsrSensitivity = FALSE;
  480. g_phpstate->dcb.fDtrControl = DTR_CONTROL_ENABLE;
  481. if (!SetCommState(g_phpstate->hComPort, &g_phpstate->dcb)) {
  482. _JumpLastError(hr, error, "SetCommState");
  483. }
  484. // create the events used by the hw prov
  485. g_phpstate->hStopEvent = CreateEvent(NULL/*security*/, TRUE/*manual*/, FALSE/*state*/, NULL/*name*/);
  486. if (NULL == g_phpstate->hStopEvent) {
  487. _JumpLastError(hr, error, "CreateEvent");
  488. }
  489. g_phpstate->hProvThread_EnterOrLeaveThreadTrapEvent = CreateEvent(NULL/*security*/, FALSE/*auto*/, FALSE/*state*/, NULL/*name*/);
  490. if (NULL == g_phpstate->hProvThread_EnterOrLeaveThreadTrapEvent) {
  491. _JumpLastError(hr, error, "CreateEvent");
  492. }
  493. g_phpstate->hProvThread_ThreadTrapTransitionCompleteEvent = CreateEvent(NULL/*security*/, FALSE/*auto*/, FALSE/*state*/, NULL/*name*/);
  494. if (NULL == g_phpstate->hProvThread_ThreadTrapTransitionCompleteEvent) {
  495. _JumpLastError(hr, error, "CreateEvent");
  496. }
  497. g_phpstate->hProvThread = CreateThread(NULL, NULL, HwProvThread, NULL, 0, &dwThreadID);
  498. if (NULL == g_phpstate->hProvThread) {
  499. _JumpLastError(hr, error, "CreateThread");
  500. }
  501. hr = S_OK;
  502. error:
  503. if (NULL != phpc) {
  504. FreeHwProvConfig(phpc);
  505. }
  506. if (FAILED(hr)) {
  507. StopHwProv();
  508. }
  509. return hr;
  510. }
  511. //--------------------------------------------------------------------------------
  512. //
  513. // PROVIDER INTERFACE IMPLEMENTATION
  514. //
  515. //--------------------------------------------------------------------------------
  516. //--------------------------------------------------------------------
  517. HRESULT __stdcall
  518. TimeProvOpen(IN WCHAR * wszName, IN TimeProvSysCallbacks * pSysCallbacks, OUT TimeProvHandle * phTimeProv) {
  519. HRESULT hr;
  520. if (NULL != g_phpstate) {
  521. hr=HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
  522. _JumpError(hr, error, "(provider init)");
  523. }
  524. hr = StartHwProv(pSysCallbacks);
  525. _JumpIfError(hr, error, "StartHwProv");
  526. *phTimeProv = 0; /*ignored*/
  527. hr=S_OK;
  528. error:
  529. return hr;
  530. }
  531. //--------------------------------------------------------------------
  532. HRESULT __stdcall
  533. TimeProvCommand(IN TimeProvHandle hTimeProv, IN TimeProvCmd eCmd, IN TimeProvArgs pvArgs) {
  534. HRESULT hr;
  535. LPCWSTR wszProv;
  536. if (0 != hTimeProv) {
  537. hr = HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE);
  538. _JumpError(hr, error, "HwTimeProvCommand: provider handle verification");
  539. }
  540. switch (eCmd)
  541. {
  542. case TPC_TimeJumped:
  543. hr = HandleTimeJump((TpcTimeJumpedArgs *)pvArgs);
  544. _JumpIfError(hr, error, "HandleTimeJump");
  545. break;
  546. case TPC_UpdateConfig:
  547. hr = HandleUpdateConfig();
  548. _JumpIfError(hr, error, "HandleUpdateConfig");
  549. break;
  550. case TPC_GetSamples:
  551. hr = HandleGetSamples((TpcGetSamplesArgs *)pvArgs);
  552. _JumpIfError(hr, error, "HandleGetSamples");
  553. break;
  554. case TPC_PollIntervalChanged: // BUGBUG: unnecessary until we add support for polling
  555. case TPC_NetTopoChange: // unnecessary for HW prov
  556. // Don't need to do anything here.
  557. break;
  558. case TPC_Query:
  559. hr = HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED);
  560. _JumpError(hr, error, "HwTimeProvCommand");
  561. case TPC_Shutdown:
  562. hr=StopHwProv();
  563. _JumpIfError(hr, error, "StopHwProv");
  564. break;
  565. default:
  566. hr=HRESULT_FROM_WIN32(ERROR_BAD_COMMAND);
  567. _JumpError(hr, error, "(command dispatch)");
  568. }
  569. hr=S_OK;
  570. error:
  571. return hr;
  572. }
  573. //--------------------------------------------------------------------
  574. HRESULT __stdcall
  575. TimeProvClose(IN TimeProvHandle hTimeProv) {
  576. HRESULT hr;
  577. LPCWSTR wszProv;
  578. if (0 != hTimeProv) {
  579. hr=HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE);
  580. _JumpError(hr, error, "(provider handle verification)");
  581. }
  582. hr=StopHwProv();
  583. _JumpIfError(hr, error, "StopHwServer");
  584. hr=S_OK;
  585. error:
  586. return hr;
  587. }