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.

421 lines
12 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1996 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: moninfo.c
  6. * Content: Code to query monitor specifications
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 24-mar-96 kylej initial implementation (code from Toddla)
  12. *@@END_MSINTERNAL
  13. *
  14. ***************************************************************************/
  15. #include <windows.h>
  16. #include <windowsx.h>
  17. #include <minivdd.h>
  18. #include "edid.h"
  19. #pragma optimize("gle", off)
  20. #define Not_VxD
  21. #include <vmm.h>
  22. #include <configmg.h>
  23. #pragma optimize("", on)
  24. #include "ddraw16.h"
  25. /***************************************************************************
  26. * just incase these are not defined, define them localy.
  27. ***************************************************************************/
  28. #ifndef VDD_OPEN
  29. #define VDD_OPEN (13 + MINIVDD_SVC_BASE_OFFSET)
  30. #endif
  31. #ifndef VDD_OPEN_TEST
  32. #define VDD_OPEN_TEST 0x00000001
  33. #endif
  34. /***************************************************************************
  35. ***************************************************************************/
  36. static int myatoi(LPSTR sz)
  37. {
  38. int i=0;
  39. int sign=+1;
  40. if (*sz=='-')
  41. {
  42. sign=-1;
  43. sz++;
  44. }
  45. while (*sz && *sz >= '0' && *sz <= '9')
  46. i = i*10 + (*sz++-'0');
  47. return i*sign;
  48. }
  49. /***************************************************************************
  50. VDDCall - make a service call into the VDD
  51. ***************************************************************************/
  52. #pragma optimize("gle", off)
  53. DWORD VDDCall(DWORD dev, DWORD function, DWORD flags, LPVOID buffer, DWORD buffer_size)
  54. {
  55. static DWORD VDDEntryPoint=0;
  56. DWORD result=0xFFFFFFFF;
  57. if (VDDEntryPoint == 0)
  58. {
  59. _asm
  60. {
  61. xor di,di ;set these to zero before calling
  62. mov es,di ;
  63. mov ax,1684h ;INT 2FH: Get VxD API Entry Point
  64. mov bx,0ah ;this is device code for VDD
  65. int 2fh ;call the multiplex interrupt
  66. mov word ptr VDDEntryPoint[0],di ;
  67. mov word ptr VDDEntryPoint[2],es ;save the returned data
  68. }
  69. if (VDDEntryPoint == 0)
  70. return result;
  71. }
  72. _asm
  73. {
  74. _emit 66h _asm push si ; push esi
  75. _emit 66h _asm push di ; push edi
  76. _emit 66h _asm mov ax,word ptr function ;eax = function
  77. _emit 66h _asm mov bx,word ptr dev ;ebx = device
  78. _emit 66h _asm mov cx,word ptr buffer_size ;ecx = buffer_size
  79. _emit 66h _asm mov dx,word ptr flags ;edx = flags
  80. _emit 66h _asm xor di,di ; HIWORD(edi)=0
  81. les di,buffer
  82. mov si,di ;si
  83. call dword ptr VDDEntryPoint ;call the VDD's PM API
  84. cmp ax,word ptr function
  85. je fail
  86. _emit 66h _asm mov word ptr result,ax
  87. fail: _emit 66h _asm pop di ; pop edi
  88. _emit 66h _asm pop si ; pop esi
  89. }
  90. return result;
  91. }
  92. #pragma optimize("", on)
  93. /***************************************************************************
  94. * GetDisplayInfo - call the VDD to get the DISPLAYINFO for a device
  95. *
  96. * input
  97. * szDevice - device name, use NULL or "DISPLAY" for primary device.
  98. *
  99. * output
  100. * DISPLAYINFO filled in
  101. *
  102. ***************************************************************************/
  103. DWORD NEAR GetDisplayInfo(LPSTR szDevice, DISPLAYINFO FAR *pdi)
  104. {
  105. DWORD dev;
  106. if (szDevice && lstrcmpi(szDevice, "DISPLAY") != 0)
  107. dev = VDDCall(0, VDD_OPEN, VDD_OPEN_TEST, (LPVOID)szDevice, 0);
  108. else
  109. dev = 1;
  110. if (dev == 0 || dev == 0xFFFFFFFF)
  111. return 0;
  112. pdi->diHdrSize = sizeof(DISPLAYINFO);
  113. pdi->diDevNodeHandle = 0;
  114. pdi->diMonitorDevNodeHandle = 0;
  115. VDDCall(dev, VDD_GET_DISPLAY_CONFIG, 0, (LPVOID)pdi, sizeof(DISPLAYINFO));
  116. if (pdi->diDevNodeHandle == 0)
  117. return 0;
  118. else
  119. return dev;
  120. }
  121. /***************************************************************************
  122. * GetMonitorMaxSize - returns the max xresolution the monitor supports
  123. *
  124. * input
  125. * szDevice - device name, use NULL or "DISPLAY" for primary device.
  126. *
  127. * output
  128. * max xresolution of the monitor, or zero if the monitor
  129. * is unknown.
  130. *
  131. ***************************************************************************/
  132. int DDAPI DD16_GetMonitorMaxSize(LPSTR szDevice)
  133. {
  134. DISPLAYINFO di;
  135. char ach[40];
  136. DWORD cb;
  137. GetDisplayInfo(szDevice, &di);
  138. if (di.diMonitorDevNodeHandle == 0)
  139. return 0;
  140. //
  141. // we have the devnode handle for the monitor, read the max
  142. // size from the registry, first try the HW key then the SW
  143. // key, this way PnP monitors will be supported.
  144. //
  145. ach[0] = 0;
  146. cb = sizeof(ach);
  147. CM_Read_Registry_Value(di.diMonitorDevNodeHandle, NULL, "MaxResolution",
  148. REG_SZ, ach, &cb, CM_REGISTRY_HARDWARE);
  149. if (ach[0] == 0)
  150. {
  151. cb = sizeof(ach);
  152. CM_Read_Registry_Value(di.diMonitorDevNodeHandle, NULL, "MaxResolution",
  153. REG_SZ, ach, &cb, CM_REGISTRY_SOFTWARE);
  154. }
  155. //
  156. // ach now contains the maxres, ie "1024,768" convert the xres to a
  157. // integer and return it.
  158. //
  159. return myatoi(ach);
  160. }
  161. /***************************************************************************
  162. * GetMonitorRefreshRateRanges
  163. *
  164. * returns the min/max refresh rate ranges for a given mode
  165. *
  166. * input
  167. * szDevice - device name, use NULL (or "DISPLAY") for the primary device.
  168. * xres - xres of the mode to query refresh ranges for
  169. * yres - yres of the mode to query refresh ranges for
  170. * pmin - place to put min refresh
  171. * pmax - place to put max refresh
  172. *
  173. * output
  174. * true if success
  175. * is unknown.
  176. *
  177. ***************************************************************************/
  178. BOOL DDAPI DD16_GetMonitorRefreshRateRanges(LPSTR szDevice, int xres, int yres, int FAR *pmin, int FAR *pmax)
  179. {
  180. DISPLAYINFO di;
  181. char ach[40];
  182. DWORD cb;
  183. HKEY hkey;
  184. char SaveRes[40];
  185. char SaveRate[40];
  186. DWORD dev;
  187. //
  188. // set these to zero in case we fail
  189. //
  190. *pmin = 0;
  191. *pmax = 0;
  192. //
  193. // get the devnode handle for the display
  194. //
  195. dev = GetDisplayInfo(szDevice, &di);
  196. if (di.diDevNodeHandle == 0)
  197. return 0;
  198. //
  199. // open the settings key for the device, if no custom key exists
  200. // use HKCC/Display/Settings
  201. //
  202. hkey = NULL;
  203. VDDCall(dev, VDD_OPEN_KEY, 0, &hkey, sizeof(hkey));
  204. if (hkey == NULL)
  205. RegOpenKey(HKEY_CURRENT_CONFIG, "Display\\Settings", &hkey);
  206. if (hkey == NULL)
  207. return 0;
  208. //
  209. // save the current values of RefreshRate, and Resolution
  210. //
  211. SaveRate[0] = 0;
  212. SaveRes[0] = 0;
  213. cb = sizeof(SaveRes);
  214. RegQueryValueEx(hkey, "Resolution", NULL, NULL, SaveRes, &cb);
  215. cb = sizeof(SaveRate);
  216. CM_Read_Registry_Value(di.diDevNodeHandle, "DEFAULT", "RefreshRate",
  217. REG_SZ, SaveRate, &cb, CM_REGISTRY_SOFTWARE);
  218. //
  219. // set our new values, the VDD uses the resoluton in the
  220. // registry when computing the refresh rate ranges so we need
  221. // to update the registry to contain the mode we want to test.
  222. // we also need to write RefreshRate=-1 to enable automatic
  223. // refresh rate calcultion.
  224. //
  225. cb = wsprintf(ach, "%d,%d", xres, yres);
  226. RegSetValueEx(hkey, "Resolution", NULL, REG_SZ, ach, cb);
  227. CM_Write_Registry_Value(di.diDevNodeHandle, "DEFAULT", "RefreshRate",
  228. REG_SZ, "-1", 2, CM_REGISTRY_SOFTWARE);
  229. //
  230. // now call the VDD to get the refresh rate info.
  231. //
  232. di.diHdrSize = sizeof(DISPLAYINFO);
  233. di.diRefreshRateMin = 0;
  234. di.diRefreshRateMax = 0;
  235. VDDCall(dev, VDD_GET_DISPLAY_CONFIG, 0, (LPVOID)&di, sizeof(DISPLAYINFO));
  236. *pmin = di.diRefreshRateMin;
  237. *pmax = di.diRefreshRateMax;
  238. //
  239. // restore the saved values back to the registry
  240. //
  241. CM_Write_Registry_Value(di.diDevNodeHandle, "DEFAULT", "RefreshRate",
  242. REG_SZ, SaveRate, lstrlen(SaveRate), CM_REGISTRY_SOFTWARE);
  243. RegSetValueEx(hkey, "Resolution", NULL, REG_SZ, SaveRes, lstrlen(SaveRes));
  244. RegCloseKey(hkey);
  245. return TRUE;
  246. }
  247. /***************************************************************************
  248. * GetDeviceConfig
  249. *
  250. * get the device resource config
  251. *
  252. * input
  253. * szDevice - device name, use NULL (or "DISPLAY") for the primary device.
  254. * lpConfig - points to a CMCONFIG struct (or NULL)
  255. * cbConfig - size of lpConfig buffer
  256. *
  257. * output
  258. * return the devnode handle, or 0 if failure
  259. *
  260. ***************************************************************************/
  261. DWORD DDAPI DD16_GetDeviceConfig(LPSTR szDevice, LPVOID lpConfig, DWORD cbConfig)
  262. {
  263. DISPLAYINFO di;
  264. //
  265. // get the devnode handle for the display
  266. //
  267. GetDisplayInfo(szDevice, &di);
  268. if (di.diDevNodeHandle == 0)
  269. return 0;
  270. //
  271. // call CONFIGMG to get the config
  272. //
  273. if (lpConfig)
  274. {
  275. if (cbConfig < sizeof(CMCONFIG))
  276. return 0;
  277. CM_Get_Alloc_Log_Conf((CMCONFIG FAR *)lpConfig, di.diDevNodeHandle, 0);
  278. }
  279. //
  280. // return the DEVNODE handle
  281. //
  282. return di.diDevNodeHandle;
  283. }
  284. /***************************************************************************
  285. * GetMonitorEDIDData
  286. *
  287. * input
  288. * szDevice - device name, use NULL or "DISPLAY" for primary device.
  289. *
  290. * output
  291. * lpEdidData - EDID data.
  292. *
  293. ***************************************************************************/
  294. int DDAPI DD16_GetMonitorEDIDData(LPSTR szDevice, LPVOID lpEdidData)
  295. {
  296. DISPLAYINFO di;
  297. DWORD cb;
  298. GetDisplayInfo(szDevice, &di);
  299. if (di.diMonitorDevNodeHandle == 0)
  300. return 0;
  301. cb = sizeof( VESA_EDID );
  302. if (CM_Read_Registry_Value(di.diMonitorDevNodeHandle, NULL, "EDID", REG_BINARY, lpEdidData, &cb, CM_REGISTRY_HARDWARE) == CR_SUCCESS)
  303. {
  304. return TRUE;
  305. }
  306. return FALSE;
  307. }
  308. /***************************************************************************
  309. * GetRateFromRegistry
  310. *
  311. * input
  312. * szDevice - device name, use NULL or "DISPLAY" for primary device.
  313. *
  314. ***************************************************************************/
  315. DWORD DDAPI DD16_GetRateFromRegistry(LPSTR szDevice)
  316. {
  317. DISPLAYINFO di;
  318. DWORD cb;
  319. BYTE szTemp[20];
  320. //
  321. // get the devnode handle for the display
  322. //
  323. GetDisplayInfo(szDevice, &di);
  324. if (di.diDevNodeHandle == 0)
  325. return 0;
  326. cb = sizeof( szTemp );
  327. if (CM_Read_Registry_Value(di.diDevNodeHandle, "DEFAULT", "RefreshRate", REG_SZ, szTemp, &cb, CM_REGISTRY_SOFTWARE) == CR_SUCCESS)
  328. {
  329. return atoi( szTemp );
  330. }
  331. return 0;
  332. }
  333. /***************************************************************************
  334. * SetRateInRegistry
  335. *
  336. * input
  337. * szDevice - device name, use NULL or "DISPLAY" for primary device.
  338. * dwRate - Rate to set in the registry
  339. *
  340. ***************************************************************************/
  341. int DDAPI DD16_SetRateInRegistry(LPSTR szDevice, DWORD dwRate)
  342. {
  343. DISPLAYINFO di;
  344. DWORD cb;
  345. BYTE szTemp[20];
  346. //
  347. // get the devnode handle for the display
  348. //
  349. GetDisplayInfo(szDevice, &di);
  350. if (di.diDevNodeHandle == 0)
  351. return 0;
  352. wsprintf( szTemp, "%d", (int)dwRate );
  353. cb = lstrlen( szTemp ) ;
  354. CM_Write_Registry_Value(di.diDevNodeHandle, "DEFAULT", "RefreshRate", REG_SZ, szTemp, cb, CM_REGISTRY_SOFTWARE);
  355. return 0;
  356. }