2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Display Control Panel
4 * FILE: dll/cpl/desk/devsett.c
5 * PURPOSE: ReactOS Display Control Panel Shell Extension Support
13 #define DEBUG_DEVSETTINGS
15 typedef struct _CDevSettings
17 const struct IDataObjectVtbl
*lpIDataObjectVtbl
;
20 CLIPFORMAT cfExtInterface
; /* "Desk.cpl extension interface" */
21 CLIPFORMAT cfDisplayDevice
; /* "Display Device" */
22 CLIPFORMAT cfDisplayName
; /* "Display Name" */
23 CLIPFORMAT cfDisplayId
; /* "Display ID" */
24 CLIPFORMAT cfMonitorName
; /* "Monitor Name" */
25 CLIPFORMAT cfMonitorDevice
; /* "Monitor Device" */
26 CLIPFORMAT cfDisplayKey
; /* "Display Key" */
27 CLIPFORMAT cfDisplayStateFlags
; /* "Display State Flags" */
28 CLIPFORMAT cfPruningMode
; /* "Pruning Mode" */
37 DESK_EXT_INTERFACE ExtInterface
;
46 DWORD bModesPruned
: 1;
47 DWORD bKeyIsReadOnly
: 1;
51 } CDevSettings
, *PCDevSettings
;
53 #define impl_to_interface(impl,iface) (struct iface *)(&(impl)->lp##iface##Vtbl)
55 static __inline PCDevSettings
56 impl_from_IDataObject(struct IDataObject
*iface
)
58 return (PCDevSettings
)((ULONG_PTR
)iface
- FIELD_OFFSET(CDevSettings
,
63 pCDevSettings_FreeString(PWCHAR
*psz
)
67 LocalFree((HLOCAL
)*psz
);
73 pCDevSettings_AllocAndCopyString(const TCHAR
*pszSrc
)
78 c
= _tcslen(pszSrc
) + 1;
79 str
= (PWSTR
)LocalAlloc(LMEM_FIXED
,
87 MultiByteToWideChar(CP_ACP
,
100 pCDevSettings_GetMonitorName(const WCHAR
*pszDisplayDevice
)
102 DISPLAY_DEVICEW dd
, dd2
;
106 if (EnumDisplayDevicesW(pszDisplayDevice
,
111 dd2
.cb
= sizeof(dd2
);
112 if (EnumDisplayDevicesW(pszDisplayDevice
,
117 /* There's more than one monitor connected... */
119 IDS_MULTIPLEMONITORS
,
121 sizeof(dd
.DeviceString
) / sizeof(dd
.DeviceString
[0]));
126 /* We can't enumerate a monitor, make sure this fact is reported
131 sizeof(dd
.DeviceString
) / sizeof(dd
.DeviceString
[0]));
134 str
= LocalAlloc(LMEM_FIXED
,
135 (wcslen(dd
.DeviceString
) + 1) * sizeof(WCHAR
));
146 pCDevSettings_GetMonitorDevice(const WCHAR
*pszDisplayDevice
)
152 if (EnumDisplayDevicesW(pszDisplayDevice
,
157 str
= LocalAlloc(LMEM_FIXED
,
158 (wcslen(dd
.DeviceName
) + 1) * sizeof(WCHAR
));
170 pCDevSettings_GetDeviceInstanceId(const WCHAR
*pszDevice
)
175 LPWSTR lpDevInstId
= NULL
;
177 DPRINT1("CDevSettings::GetDeviceInstanceId(%ws) UNIMPLEMENTED!\n", pszDevice
);
179 cr
= CM_Locate_DevNodeW(&DevInst
,
180 (DEVINSTID_W
)pszDevice
,
181 CM_LOCATE_DEVNODE_NORMAL
);
182 if (cr
== CR_SUCCESS
)
184 DPRINT1("Success1\n");
185 cr
= CM_Get_Device_ID_Size(&BufLen
,
188 if (cr
== CR_SUCCESS
)
190 DPRINT1("Success2\n");
191 lpDevInstId
= LocalAlloc(LMEM_FIXED
,
192 (BufLen
+ 1) * sizeof(WCHAR
));
194 if (lpDevInstId
!= NULL
)
196 DPRINT1("Success3\n");
197 cr
= CM_Get_Device_IDW(DevInst
,
202 if (cr
!= CR_SUCCESS
)
204 LocalFree((HLOCAL
)lpDevInstId
);
207 DPRINT1("instance id: %ws\n", lpDevInstId
);
217 pCDevSettings_OpenDeviceKey(PCDevSettings This
,
220 static const WCHAR szRegPrefix
[] = L
"\\Registry\\Machine\\";
222 REGSAM Access
= KEY_READ
;
225 lpRegKey
= This
->pDisplayKey
;
226 if (lpRegKey
!= NULL
)
228 if (wcslen(lpRegKey
) >= wcslen(szRegPrefix
) &&
231 wcslen(szRegPrefix
)))
233 lpRegKey
+= wcslen(szRegPrefix
);
239 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
243 &hKey
) == ERROR_SUCCESS
)
252 PDEVMODEW DESK_EXT_CALLBACK
253 CDevSettings_EnumAllModes(PVOID Context
,
256 //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
257 /* FIXME: Implement */
258 DPRINT1("CDevSettings::EnumAllModes(%u)\n", Index
);
262 PDEVMODEW DESK_EXT_CALLBACK
263 CDevSettings_GetCurrentMode(PVOID Context
)
265 //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
266 /* FIXME: Implement */
267 DPRINT1("CDevSettings::GetCurrentMode\n");
271 BOOL DESK_EXT_CALLBACK
272 CDevSettings_SetCurrentMode(PVOID Context
,
273 const DEVMODEW
*pDevMode
)
275 //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
276 /* FIXME: Implement */
277 DPRINT1("CDevSettings::SetCurrentMode(0x%p)\n", pDevMode
);
281 VOID DESK_EXT_CALLBACK
282 CDevSettings_GetPruningMode(PVOID Context
,
284 PBOOL pbKeyIsReadOnly
,
287 PCDevSettings This
= impl_from_IDataObject((IDataObject
*)Context
);
289 DPRINT1("CDevSettings::GetPruningMode(%p,%p,%p)\n", pbModesPruned
, pbKeyIsReadOnly
, pbPruningOn
);
291 *pbModesPruned
= This
->bModesPruned
;
292 *pbKeyIsReadOnly
= This
->bKeyIsReadOnly
;
293 *pbPruningOn
= This
->bPruningOn
;
296 VOID DESK_EXT_CALLBACK
297 CDevSettings_SetPruningMode(PVOID Context
,
302 PCDevSettings This
= impl_from_IDataObject((IDataObject
*)Context
);
304 DPRINT1("CDevSettings::SetPruningMode(%d)\n", PruningOn
);
306 if (This
->bModesPruned
&& !This
->bKeyIsReadOnly
&&
307 PruningOn
!= This
->bPruningOn
)
309 This
->bPruningOn
= (PruningOn
!= FALSE
);
311 hKey
= pCDevSettings_OpenDeviceKey(This
,
315 dwValue
= (DWORD
)This
->bPruningOn
;
321 (const BYTE
*)&dwValue
,
330 pCDevSettings_ReadHardwareInfo(HKEY hKey
,
334 DWORD type
= REG_BINARY
;
335 DWORD size
= 128 * sizeof(WCHAR
);
336 RegQueryValueEx(hKey
,
345 pCDevSettings_InitializeExtInterface(PCDevSettings This
)
347 PDESK_EXT_INTERFACE Interface
= &This
->ExtInterface
;
350 ZeroMemory(Interface
,
352 Interface
->cbSize
= sizeof(*Interface
);
354 /* Initialize the callback table */
355 Interface
->Context
= impl_to_interface(This
, IDataObject
);
356 Interface
->EnumAllModes
= CDevSettings_EnumAllModes
;
357 Interface
->SetCurrentMode
= CDevSettings_SetCurrentMode
;
358 Interface
->GetCurrentMode
= CDevSettings_GetCurrentMode
;
359 Interface
->SetPruningMode
= CDevSettings_SetPruningMode
;
360 Interface
->GetPruningMode
= CDevSettings_GetPruningMode
;
362 /* Read the HardwareInformation.* values from the registry key */
363 hKeyDev
= pCDevSettings_OpenDeviceKey(This
,
367 DWORD dwType
, dwMemSize
= 0;
368 DWORD dwSize
= sizeof(dwMemSize
);
370 if (RegQueryValueEx(hKeyDev
,
371 TEXT("HardwareInformation.MemorySize"),
375 &dwSize
) == ERROR_SUCCESS
&&
376 (dwType
== REG_BINARY
|| dwType
== REG_DWORD
) &&
377 dwSize
== sizeof(dwMemSize
))
381 if (dwMemSize
> 1024)
384 if (dwMemSize
> 1024)
386 wsprintf(Interface
->MemorySize
,
392 wsprintf(Interface
->MemorySize
,
399 wsprintf(Interface
->MemorySize
,
405 pCDevSettings_ReadHardwareInfo(hKeyDev
,
406 TEXT("HardwareInformation.ChipType"),
407 Interface
->ChipType
);
408 pCDevSettings_ReadHardwareInfo(hKeyDev
,
409 TEXT("HardwareInformation.DacType"),
411 pCDevSettings_ReadHardwareInfo(hKeyDev
,
412 TEXT("HardwareInformation.AdapterString"),
413 Interface
->AdapterString
);
414 pCDevSettings_ReadHardwareInfo(hKeyDev
,
415 TEXT("HardwareInformation.BiosString"),
416 Interface
->BiosString
);
417 RegCloseKey(hKeyDev
);
422 pCDevSettings_Initialize(PCDevSettings This
,
423 PDISPLAY_DEVICE_ENTRY DisplayDeviceInfo
)
428 This
->StateFlags
= DisplayDeviceInfo
->DeviceStateFlags
;
429 DPRINT1("This->StateFlags: %x\n", This
->StateFlags
);
431 /* Register clipboard formats */
432 This
->cfExtInterface
= RegisterClipboardFormat(DESK_EXT_EXTINTERFACE
);
433 This
->cfDisplayDevice
= RegisterClipboardFormat(DESK_EXT_DISPLAYDEVICE
);
434 This
->cfDisplayName
= RegisterClipboardFormat(DESK_EXT_DISPLAYNAME
);
435 This
->cfDisplayId
= RegisterClipboardFormat(DESK_EXT_DISPLAYID
);
436 This
->cfDisplayKey
= RegisterClipboardFormat(DESK_EXT_DISPLAYKEY
);
437 This
->cfDisplayStateFlags
= RegisterClipboardFormat(DESK_EXT_DISPLAYSTATEFLAGS
);
438 This
->cfMonitorName
= RegisterClipboardFormat(DESK_EXT_MONITORNAME
);
439 This
->cfMonitorDevice
= RegisterClipboardFormat(DESK_EXT_MONITORDEVICE
);
440 This
->cfPruningMode
= RegisterClipboardFormat(DESK_EXT_PRUNINGMODE
);
442 /* Copy the device name */
443 This
->pDisplayDevice
= pCDevSettings_AllocAndCopyString(DisplayDeviceInfo
->DeviceName
);
444 DPRINT1("This->pDisplayDevice: %ws\n", This
->pDisplayDevice
);
445 This
->pDisplayName
= pCDevSettings_AllocAndCopyString(DisplayDeviceInfo
->DeviceDescription
);
446 DPRINT1("This->pDisplayName: %ws\n", This
->pDisplayName
);
447 This
->pDisplayKey
= pCDevSettings_AllocAndCopyString(DisplayDeviceInfo
->DeviceKey
);
448 DPRINT1("This->pDisplayKey: %ws\n", This
->pDisplayKey
);
449 This
->pDisplayId
= pCDevSettings_GetDeviceInstanceId(DisplayDeviceInfo
->DeviceID
);
450 DPRINT1("This->pDisplayId: %ws\n", This
->pDisplayId
);
451 This
->pMonitorName
= pCDevSettings_GetMonitorName(This
->pDisplayDevice
);
452 DPRINT1("This->pMonitorName: %ws\n", This
->pMonitorName
);
453 This
->pMonitorDevice
= pCDevSettings_GetMonitorDevice(This
->pDisplayDevice
);
454 DPRINT1("This->pMonitorDevice: %ws\n", This
->pMonitorDevice
);
456 /* Check pruning mode */
457 This
->bModesPruned
= ((DisplayDeviceInfo
->DeviceStateFlags
& DISPLAY_DEVICE_MODESPRUNED
) != 0);
458 hKey
= pCDevSettings_OpenDeviceKey(This
,
462 hKey
= pCDevSettings_OpenDeviceKey(This
,
464 This
->bKeyIsReadOnly
= TRUE
;
469 DWORD dwType
, dwSize
;
472 if (RegQueryValueEx(hKey
,
477 &dwSize
) == ERROR_SUCCESS
)
479 if (dwType
== REG_DWORD
&& dwSize
== sizeof(dw
))
480 This
->bPruningOn
= (dw
!= 0);
486 /* Initialize the shell extension interface */
487 pCDevSettings_InitializeExtInterface(This
);
493 pCDevSettings_Free(PCDevSettings This
)
495 pCDevSettings_FreeString(&This
->pDisplayDevice
);
496 pCDevSettings_FreeString(&This
->pDisplayName
);
497 pCDevSettings_FreeString(&This
->pDisplayKey
);
498 pCDevSettings_FreeString(&This
->pDisplayId
);
499 pCDevSettings_FreeString(&This
->pMonitorName
);
500 pCDevSettings_FreeString(&This
->pMonitorDevice
);
503 static HRESULT STDMETHODCALLTYPE
504 CDevSettings_QueryInterface(IDataObject
* iface
,
508 PCDevSettings This
= impl_from_IDataObject(iface
);
512 if (IsEqualGUID(riid
,
517 *ppvObject
= (PVOID
)impl_to_interface(This
, IDataObject
);
522 DPRINT1("CDevSettings::QueryInterface: Queried unknown interface\n");
525 return E_NOINTERFACE
;
528 static ULONG STDMETHODCALLTYPE
529 CDevSettings_AddRef(IDataObject
* iface
)
531 PCDevSettings This
= impl_from_IDataObject(iface
);
532 return (ULONG
)InterlockedIncrement((PLONG
)&This
->ref
);
535 static ULONG STDMETHODCALLTYPE
536 CDevSettings_Release(IDataObject
* iface
)
539 PCDevSettings This
= impl_from_IDataObject(iface
);
540 refs
= (ULONG
)InterlockedDecrement((PLONG
)&This
->ref
);
542 pCDevSettings_Free(This
);
547 static HRESULT STDMETHODCALLTYPE
548 CDevSettings_GetData(IDataObject
* iface
,
549 FORMATETC
* pformatetcIn
,
552 static const WCHAR szEmpty
[] = {0};
554 PCWSTR pszRet
= NULL
;
556 PCDevSettings This
= impl_from_IDataObject(iface
);
561 hr
= IDataObject_QueryGetData(iface
,
565 /* Return the reqested data back to the shell extension */
567 if (pformatetcIn
->cfFormat
== This
->cfDisplayDevice
)
569 pszRet
= This
->pDisplayDevice
;
570 DPRINT1("CDevSettings::GetData returns display device %ws\n", pszRet
);
572 else if (pformatetcIn
->cfFormat
== This
->cfDisplayName
)
574 pszRet
= This
->pDisplayName
;
575 DPRINT1("CDevSettings::GetData returns display name %ws\n", pszRet
);
577 else if (pformatetcIn
->cfFormat
== This
->cfDisplayKey
)
579 pszRet
= This
->pDisplayKey
;
580 DPRINT1("CDevSettings::GetData returns display key %ws\n", pszRet
);
582 else if (pformatetcIn
->cfFormat
== This
->cfDisplayId
)
584 pszRet
= This
->pDisplayId
;
585 DPRINT1("CDevSettings::GetData returns display id %ws\n", pszRet
);
587 else if (pformatetcIn
->cfFormat
== This
->cfMonitorName
)
589 pszRet
= This
->pMonitorName
;
590 DPRINT1("CDevSettings::GetData returns monitor name %ws\n", pszRet
);
592 else if (pformatetcIn
->cfFormat
== This
->cfMonitorDevice
)
594 pszRet
= This
->pMonitorDevice
;
595 DPRINT1("CDevSettings::GetData returns monitor device %ws\n", pszRet
);
597 else if (pformatetcIn
->cfFormat
== This
->cfExtInterface
)
599 PDESK_EXT_INTERFACE pIface
;
601 pIface
= GlobalAlloc(GPTR
,
607 sizeof(This
->ExtInterface
));
609 DPRINT1("CDevSettings::GetData returns the desk.cpl extension interface\n");
611 pmedium
->tymed
= TYMED_HGLOBAL
;
612 pmedium
->hGlobal
= pIface
;
617 return E_OUTOFMEMORY
;
619 else if (pformatetcIn
->cfFormat
== This
->cfDisplayStateFlags
)
623 pdw
= GlobalAlloc(GPTR
,
627 *pdw
= This
->StateFlags
;
629 DPRINT1("CDevSettings::GetData returns the display state flags %x\n", This
->StateFlags
);
631 pmedium
->tymed
= TYMED_HGLOBAL
;
632 pmedium
->hGlobal
= pdw
;
637 return E_OUTOFMEMORY
;
639 else if (pformatetcIn
->cfFormat
== This
->cfPruningMode
)
643 pb
= GlobalAlloc(GPTR
,
647 *pb
= (This
->bModesPruned
&& This
->bPruningOn
);
649 pmedium
->tymed
= TYMED_HGLOBAL
;
650 pmedium
->hGlobal
= pb
;
655 return E_OUTOFMEMORY
;
658 /* NOTE: This only returns null-terminated strings! */
662 pszBuf
= GlobalAlloc(GPTR
,
663 (_tcslen(pszRet
) + 1) * sizeof(WCHAR
));
669 pmedium
->tymed
= TYMED_HGLOBAL
;
670 pmedium
->hGlobal
= pszBuf
;
681 static HRESULT STDMETHODCALLTYPE
682 CDevSettings_GetDataHere(IDataObject
* iface
,
683 FORMATETC
* pformatetc
,
686 ZeroMemory(pformatetc
,
687 sizeof(*pformatetc
));
691 static HRESULT STDMETHODCALLTYPE
692 CDevSettings_QueryGetData(IDataObject
* iface
,
693 FORMATETC
* pformatetc
)
696 TCHAR szFormatName
[255];
698 PCDevSettings This
= impl_from_IDataObject(iface
);
700 if (pformatetc
->dwAspect
!= DVASPECT_CONTENT
)
701 return DV_E_DVASPECT
;
703 if (pformatetc
->lindex
!= -1)
706 if (!(pformatetc
->tymed
& TYMED_HGLOBAL
))
709 /* Check if the requested data can be provided */
710 if (pformatetc
->cfFormat
== This
->cfExtInterface
||
711 pformatetc
->cfFormat
== This
->cfDisplayDevice
||
712 pformatetc
->cfFormat
== This
->cfDisplayName
||
713 pformatetc
->cfFormat
== This
->cfDisplayId
||
714 pformatetc
->cfFormat
== This
->cfDisplayKey
||
715 pformatetc
->cfFormat
== This
->cfDisplayStateFlags
||
716 pformatetc
->cfFormat
== This
->cfMonitorDevice
||
717 pformatetc
->cfFormat
== This
->cfMonitorName
||
718 pformatetc
->cfFormat
== This
->cfPruningMode
)
725 if (GetClipboardFormatName(pformatetc
->cfFormat
,
727 sizeof(szFormatName
) / sizeof(szFormatName
[0])))
729 DPRINT1("CDevSettings::QueryGetData(\"%ws\")\n", szFormatName
);
733 DPRINT1("CDevSettings::QueryGetData(Format %u)\n", (unsigned int)pformatetc
->cfFormat
);
738 return DV_E_FORMATETC
;
741 static HRESULT STDMETHODCALLTYPE
742 CDevSettings_GetCanonicalFormatEtc(IDataObject
* iface
,
743 FORMATETC
* pformatectIn
,
744 FORMATETC
* pformatetcOut
)
748 DPRINT1("CDevSettings::GetCanonicalFormatEtc\n");
750 hr
= IDataObject_QueryGetData(iface
,
754 CopyMemory(pformatetcOut
,
758 /* Make sure the data is target device independent */
759 if (pformatectIn
->ptd
== NULL
)
760 hr
= DATA_S_SAMEFORMATETC
;
763 pformatetcOut
->ptd
= NULL
;
769 ZeroMemory(pformatetcOut
,
776 static HRESULT STDMETHODCALLTYPE
777 CDevSettings_SetData(IDataObject
* iface
,
778 FORMATETC
* pformatetc
,
782 DPRINT1("CDevSettings::SetData UNIMPLEMENTED\n");
787 pCDevSettings_FillFormatEtc(FORMATETC
*pFormatEtc
,
790 pFormatEtc
->cfFormat
= cf
;
791 pFormatEtc
->ptd
= NULL
;
792 pFormatEtc
->dwAspect
= DVASPECT_CONTENT
;
793 pFormatEtc
->lindex
= -1;
794 pFormatEtc
->tymed
= TYMED_HGLOBAL
;
797 static HRESULT STDMETHODCALLTYPE
798 CDevSettings_EnumFormatEtc(IDataObject
* iface
,
800 IEnumFORMATETC
** ppenumFormatEtc
)
804 PCDevSettings This
= impl_from_IDataObject(iface
);
806 *ppenumFormatEtc
= NULL
;
808 if (dwDirection
== DATADIR_GET
)
810 pCDevSettings_FillFormatEtc(&fetc
[0],
811 This
->cfExtInterface
);
812 pCDevSettings_FillFormatEtc(&fetc
[1],
813 This
->cfDisplayDevice
);
814 pCDevSettings_FillFormatEtc(&fetc
[2],
815 This
->cfDisplayName
);
816 pCDevSettings_FillFormatEtc(&fetc
[3],
818 pCDevSettings_FillFormatEtc(&fetc
[4],
820 pCDevSettings_FillFormatEtc(&fetc
[5],
821 This
->cfDisplayStateFlags
);
822 pCDevSettings_FillFormatEtc(&fetc
[6],
823 This
->cfMonitorName
);
824 pCDevSettings_FillFormatEtc(&fetc
[7],
825 This
->cfMonitorDevice
);
826 pCDevSettings_FillFormatEtc(&fetc
[8],
827 This
->cfPruningMode
);
829 hr
= SHCreateStdEnumFmtEtc(sizeof(fetc
) / sizeof(fetc
[0]),
839 static HRESULT STDMETHODCALLTYPE
840 CDevSettings_DAdvise(IDataObject
* iface
,
841 FORMATETC
* pformatetc
,
843 IAdviseSink
* pAdvSink
,
844 DWORD
* pdwConnection
)
847 return OLE_E_ADVISENOTSUPPORTED
;
850 static HRESULT STDMETHODCALLTYPE
851 CDevSettings_DUnadvise(IDataObject
* iface
,
854 return OLE_E_ADVISENOTSUPPORTED
;
857 static HRESULT STDMETHODCALLTYPE
858 CDevSettings_EnumDAdvise(IDataObject
* iface
,
859 IEnumSTATDATA
** ppenumAdvise
)
861 *ppenumAdvise
= NULL
;
862 return OLE_E_ADVISENOTSUPPORTED
;
865 static const struct IDataObjectVtbl vtblIDataObject
= {
866 CDevSettings_QueryInterface
,
868 CDevSettings_Release
,
869 CDevSettings_GetData
,
870 CDevSettings_GetDataHere
,
871 CDevSettings_QueryGetData
,
872 CDevSettings_GetCanonicalFormatEtc
,
873 CDevSettings_SetData
,
874 CDevSettings_EnumFormatEtc
,
875 CDevSettings_DAdvise
,
876 CDevSettings_DUnadvise
,
877 CDevSettings_EnumDAdvise
,
881 CreateDevSettings(PDISPLAY_DEVICE_ENTRY DisplayDeviceInfo
)
885 This
= HeapAlloc(GetProcessHeap(),
890 This
->lpIDataObjectVtbl
= &vtblIDataObject
;
893 if (SUCCEEDED(pCDevSettings_Initialize(This
,
896 return impl_to_interface(This
, IDataObject
);
899 CDevSettings_Release(impl_to_interface(This
, IDataObject
));
906 DisplaySaveSettings(PVOID pContext
,
909 //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
910 DPRINT("DisplaySaveSettings() UNIMPLEMENTED!\n");
911 return DISP_CHANGE_BADPARAM
;