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.

493 lines
12 KiB

  1. /* Copyright 1999 American Power Conversion, All Rights Reserved
  2. *
  3. * Description:
  4. * Implements the UPS to the service - it does this by
  5. * either loading a UPS driver or by using the default
  6. * Generic UPS interface (simple signalling)
  7. *
  8. * Revision History:
  9. * mholly 19Apr1999 initial revision.
  10. * dsmith 29Apr1999 defaulted comm status to OK
  11. * mholly 12May1999 DLL's UPSInit no longer takes the comm port param
  12. * sberard 17May1999 added a delay to the UPSTurnOffFunction
  13. *
  14. */
  15. #include <windows.h>
  16. #include <tchar.h>
  17. #include "driver.h"
  18. #include "upsreg.h"
  19. #include "gnrcups.h"
  20. //
  21. // typedefs of function pointers to aid in
  22. // accessing functions from driver DLLs
  23. //
  24. typedef DWORD (*LPFUNCGETUPSSTATE)(void);
  25. typedef void (*LPFUNCWAITFORSTATECHANGE)(DWORD, DWORD);
  26. typedef void (*LPFUNCCANCELWAIT)(void);
  27. typedef DWORD (*LPFUNCINIT)(void);
  28. typedef void (*LPFUNCSTOP)(void);
  29. typedef void (*LPFUNCTURNUPSOFF)(DWORD);
  30. //
  31. // UPSDRIVERINTERFACE
  32. //
  33. // this struct is used to gather all the driver
  34. // interface data together in a single place, this
  35. // struct is used to dispatch function calls to
  36. // either a loaded driver dll, or to the Generic
  37. // UPS interface functions
  38. //
  39. struct UPSDRIVERINTERFACE
  40. {
  41. LPFUNCINIT Init;
  42. LPFUNCSTOP Stop;
  43. LPFUNCGETUPSSTATE GetUPSState;
  44. LPFUNCWAITFORSTATECHANGE WaitForStateChange;
  45. LPFUNCCANCELWAIT CancelWait;
  46. LPFUNCTURNUPSOFF TurnUPSOff;
  47. HINSTANCE hDll;
  48. };
  49. //
  50. // private functions used to implement the interface
  51. //
  52. static DWORD initializeGenericInterface(struct UPSDRIVERINTERFACE*);
  53. static DWORD initializeDriverInterface(struct UPSDRIVERINTERFACE*,HINSTANCE);
  54. static DWORD loadUPSMiniDriver(struct UPSDRIVERINTERFACE *);
  55. static void unloadUPSMiniDriver(struct UPSDRIVERINTERFACE *);
  56. static void clearStatusRegistryEntries(void);
  57. //
  58. // _UpsInterface
  59. //
  60. // This is a file-scope variable that is used by all
  61. // the functions to get access to the actual driver
  62. //
  63. static struct UPSDRIVERINTERFACE _UpsInterface;
  64. /**
  65. * UPSInit
  66. *
  67. * Description:
  68. *
  69. * The UPSInit function must be called before any
  70. * other function in this file
  71. *
  72. * Parameters:
  73. * None
  74. *
  75. * Returns:
  76. * UPS_INITOK: Initalization was successful
  77. * UPS_INITNOSUCHDRIVER: The configured driver DLL can't be opened
  78. * UPS_INITBADINTERFACE: The configured driver DLL doesn't support
  79. * the UPS driver interface
  80. * UPS_INITREGISTRYERROR: The 'Options' registry value is corrupt
  81. * UPS_INITCOMMOPENERROR: The comm port could not be opened
  82. * UPS_INITCOMMSETUPERROR: The comm port could not be configured
  83. * UPS_INITUNKNOWNERROR: Undefined error has occurred
  84. *
  85. */
  86. DWORD UPSInit(void)
  87. {
  88. DWORD init_err = UPS_INITOK;
  89. //
  90. // clear out any old status data
  91. //
  92. clearStatusRegistryEntries();
  93. if (UPS_INITOK == init_err) {
  94. //
  95. // either load a configured driver DLL or
  96. // use the Generic UPS interface if no driver
  97. // is specified
  98. //
  99. init_err = loadUPSMiniDriver(&_UpsInterface);
  100. }
  101. if ((UPS_INITOK == init_err) && (_UpsInterface.Init)) {
  102. //
  103. // tell the UPS interface to initialize itself
  104. //
  105. init_err = _UpsInterface.Init();
  106. }
  107. return init_err;
  108. }
  109. /**
  110. * UPSStop
  111. *
  112. * Description:
  113. * After a call to UPSStop, only the UPSInit
  114. * function is valid. This call will unload the
  115. * UPS driver interface and stop monitoring of the
  116. * UPS system
  117. *
  118. * Parameters:
  119. * None
  120. *
  121. * Returns:
  122. * None
  123. *
  124. */
  125. void UPSStop(void)
  126. {
  127. if (_UpsInterface.Stop) {
  128. _UpsInterface.Stop();
  129. }
  130. unloadUPSMiniDriver(&_UpsInterface);
  131. }
  132. /**
  133. * UPSWaitForStateChange
  134. *
  135. * Description:
  136. * Blocks until the state of the UPS differs
  137. * from the value passed in via aState or
  138. * anInterval milliseconds has expired. If
  139. * anInterval has a value of INFINITE this
  140. * function will never timeout
  141. *
  142. * Parameters:
  143. * aState: defines the state to wait for a change from,
  144. * possible values:
  145. * UPS_ONLINE
  146. * UPS_ONBATTERY
  147. * UPS_LOWBATTERY
  148. * UPS_NOCOMM
  149. *
  150. * anInterval: timeout in milliseconds, or INFINITE for
  151. * no timeout interval
  152. *
  153. * Returns:
  154. * None
  155. *
  156. */
  157. void UPSWaitForStateChange(DWORD aCurrentState, DWORD anInterval)
  158. {
  159. if (_UpsInterface.WaitForStateChange) {
  160. _UpsInterface.WaitForStateChange(aCurrentState, anInterval);
  161. }
  162. }
  163. /**
  164. * UPSGetState
  165. *
  166. * Description:
  167. * returns the current state of the UPS
  168. *
  169. * Parameters:
  170. * None
  171. *
  172. * Returns:
  173. * possible values:
  174. * UPS_ONLINE
  175. * UPS_ONBATTERY
  176. * UPS_LOWBATTERY
  177. * UPS_NOCOMM
  178. *
  179. */
  180. DWORD UPSGetState(void)
  181. {
  182. DWORD err = ERROR_INVALID_ACCESS;
  183. if (_UpsInterface.GetUPSState) {
  184. err = _UpsInterface.GetUPSState();
  185. }
  186. return err;
  187. }
  188. /**
  189. * UPSCancelWait
  190. *
  191. * Description:
  192. * interrupts pending calls to UPSWaitForStateChange
  193. * without regard to timout or state change
  194. *
  195. * Parameters:
  196. * None
  197. *
  198. * Returns:
  199. * None
  200. *
  201. */
  202. void UPSCancelWait(void)
  203. {
  204. if (_UpsInterface.CancelWait) {
  205. _UpsInterface.CancelWait();
  206. }
  207. }
  208. /**
  209. * UPSTurnOff
  210. *
  211. * Description:
  212. * Attempts to turn off the outlets on the UPS
  213. * after the specified delay. This call must
  214. * return immediately. Any work, such as a timer,
  215. * must be performed on a another thread.
  216. *
  217. * Parameters:
  218. * aTurnOffDelay: the minimum amount of time to wait before
  219. * turning off the outlets on the UPS
  220. *
  221. * Returns:
  222. * None
  223. *
  224. */
  225. void UPSTurnOff(DWORD aTurnOffDelay)
  226. {
  227. if (_UpsInterface.TurnUPSOff) {
  228. _UpsInterface.TurnUPSOff(aTurnOffDelay);
  229. }
  230. }
  231. /**
  232. * initializeGenericInterface
  233. *
  234. * Description:
  235. * Fills in the UPSDRIVERINTERFACE struct with the functions
  236. * of the Generic UPS interface
  237. *
  238. * Parameters:
  239. * anInterface: the UPSDRIVERINTERFACE structure to
  240. * fill in - the struct must have been
  241. * allocated prior to calling this function
  242. *
  243. * Returns:
  244. * ERROR_SUCCESS
  245. *
  246. */
  247. DWORD initializeGenericInterface(struct UPSDRIVERINTERFACE* anInterface)
  248. {
  249. anInterface->hDll = NULL;
  250. anInterface->Init = GenericUPSInit;
  251. anInterface->Stop = GenericUPSStop;
  252. anInterface->GetUPSState = GenericUPSGetState;
  253. anInterface->WaitForStateChange = GenericUPSWaitForStateChange;
  254. anInterface->CancelWait = GenericUPSCancelWait;
  255. anInterface->TurnUPSOff = GenericUPSTurnOff;
  256. return ERROR_SUCCESS;
  257. }
  258. /**
  259. * initializeDriverInterface
  260. *
  261. * Description:
  262. * Fills in the UPSDRIVERINTERFACE struct with the functions
  263. * of the loaded UPS driver DLL
  264. *
  265. * Parameters:
  266. * anInterface: the UPSDRIVERINTERFACE structure to
  267. * fill in - the struct must have been
  268. * allocated prior to calling this function
  269. * hDll: a handle to a UPS driver DLL
  270. *
  271. * Returns:
  272. * ERROR_SUCCESS: DLL handle was valid, and the DLL supports the
  273. * UPS driver interface
  274. *
  275. * !ERROR_SUCCESS: either the DLL handle is invalid - or the DLL
  276. * does not fully support the UPS driver interface
  277. *
  278. */
  279. DWORD initializeDriverInterface(struct UPSDRIVERINTERFACE * anInterface,
  280. HINSTANCE hDll)
  281. {
  282. DWORD err = ERROR_SUCCESS;
  283. anInterface->hDll = hDll;
  284. anInterface->Init =
  285. (LPFUNCINIT)GetProcAddress(hDll, "UPSInit");
  286. if (!anInterface->Init) {
  287. err = GetLastError();
  288. goto init_driver_end;
  289. }
  290. anInterface->Stop =
  291. (LPFUNCSTOP)GetProcAddress(hDll, "UPSStop");
  292. if (!anInterface->Stop) {
  293. err = GetLastError();
  294. goto init_driver_end;
  295. }
  296. anInterface->GetUPSState =
  297. (LPFUNCGETUPSSTATE)GetProcAddress(hDll, "UPSGetState");
  298. if (!anInterface->GetUPSState) {
  299. err = GetLastError();
  300. goto init_driver_end;
  301. }
  302. anInterface->WaitForStateChange =
  303. (LPFUNCWAITFORSTATECHANGE)GetProcAddress(hDll,
  304. "UPSWaitForStateChange");
  305. if (!anInterface->WaitForStateChange) {
  306. err = GetLastError();
  307. goto init_driver_end;
  308. }
  309. anInterface->CancelWait =
  310. (LPFUNCCANCELWAIT)GetProcAddress(hDll, "UPSCancelWait");
  311. if (!anInterface->CancelWait) {
  312. err = GetLastError();
  313. goto init_driver_end;
  314. }
  315. anInterface->TurnUPSOff =
  316. (LPFUNCTURNUPSOFF)GetProcAddress(hDll, "UPSTurnOff");
  317. if (!anInterface->TurnUPSOff) {
  318. err = GetLastError();
  319. goto init_driver_end;
  320. }
  321. init_driver_end:
  322. return err;
  323. }
  324. /**
  325. * loadUPSMiniDriver
  326. *
  327. * Description:
  328. * Fills in the UPSDRIVERINTERFACE struct with the functions
  329. * of a UPS interface, either a configured driver DLL or the
  330. * Generic UPS interface. If the configured DLL can't be
  331. * opened or does not support the interface then an error is
  332. * returned and the UPSDRIVERINTERFACE will not be initialized
  333. *
  334. * Parameters:
  335. * anInterface: the UPSDRIVERINTERFACE structure to
  336. * fill in - the struct must have been
  337. * allocated prior to calling this function
  338. *
  339. * Returns:
  340. * UPS_INITOK: driver interface is intialized
  341. *
  342. * UPS_INITNOSUCHDRIVER: the configured driver DLL can't be opened
  343. * UPS_INITBADINTERFACE: the configured driver DLL does not
  344. * fully support the UPS driver interface
  345. *
  346. */
  347. DWORD loadUPSMiniDriver(struct UPSDRIVERINTERFACE * aDriverInterface)
  348. {
  349. DWORD load_err = UPS_INITOK;
  350. DWORD err = ERROR_SUCCESS;
  351. TCHAR driver_name[MAX_PATH];
  352. HINSTANCE hDll = NULL;
  353. err = GetUPSConfigServiceDLL(driver_name, MAX_PATH);
  354. //
  355. // check to see if there is a key, and that its
  356. // value is valid (a valid key has a value that
  357. // is greater than zero characters long)
  358. //
  359. if (ERROR_SUCCESS == err && _tcslen(driver_name)) {
  360. hDll = LoadLibrary(driver_name);
  361. }
  362. else {
  363. //
  364. // NO ERROR - simply means we use the
  365. // internal generic UPS support
  366. //
  367. err = initializeGenericInterface(aDriverInterface);
  368. goto load_end;
  369. }
  370. if (!hDll) {
  371. //
  372. // the configured driver could not be opened
  373. //
  374. err = GetLastError();
  375. load_err = UPS_INITNOSUCHDRIVER;
  376. goto load_end;
  377. }
  378. err = initializeDriverInterface(aDriverInterface, hDll);
  379. if (ERROR_SUCCESS != err) {
  380. load_err = UPS_INITBADINTERFACE;
  381. goto load_end;
  382. }
  383. load_end:
  384. return load_err;
  385. }
  386. /**
  387. * unloadUPSMiniDriver
  388. *
  389. * Description:
  390. * unloads a driver DLL if one was opened, also clears
  391. * out the function dispatch pointers
  392. *
  393. * Parameters:
  394. * anInterface: the UPSDRIVERINTERFACE structure to
  395. * check for DLL info, and to clear
  396. *
  397. * Returns:
  398. * None
  399. *
  400. */
  401. void unloadUPSMiniDriver(struct UPSDRIVERINTERFACE * aDriverInterface)
  402. {
  403. if (aDriverInterface) {
  404. if (aDriverInterface->hDll) {
  405. FreeLibrary(aDriverInterface->hDll);
  406. aDriverInterface->hDll = NULL;
  407. }
  408. aDriverInterface->CancelWait = NULL;
  409. aDriverInterface->GetUPSState = NULL;
  410. aDriverInterface->Init = NULL;
  411. aDriverInterface->Stop = NULL;
  412. aDriverInterface->TurnUPSOff = NULL;
  413. aDriverInterface->WaitForStateChange = NULL;
  414. }
  415. }
  416. /**
  417. * clearStatusRegistryEntries
  418. *
  419. * Description:
  420. * zeros out the registry status entries
  421. *
  422. * Parameters:
  423. * None
  424. *
  425. * Returns:
  426. * None
  427. *
  428. */
  429. void clearStatusRegistryEntries(void)
  430. {
  431. InitUPSStatusBlock();
  432. SetUPSStatusSerialNum(_TEXT(""));
  433. SetUPSStatusFirmRev(_TEXT(""));
  434. SetUPSStatusUtilityStatus(UPS_UTILITYPOWER_UNKNOWN);
  435. SetUPSStatusRuntime(0);
  436. SetUPSStatusBatteryStatus(UPS_BATTERYSTATUS_UNKNOWN);
  437. SetUPSStatusCommStatus(UPS_COMMSTATUS_OK);
  438. SaveUPSStatusBlock(TRUE);
  439. }