/***************************************************************************** * * diqacq.c * * The dialog box that tinkers with the control panel interface. * *****************************************************************************/ #include "diquick.h" #include #include #define JOY_HWS_ISGAMEPORTDRIVER 0x04000000l #define JOY_HWS_ISANALOGPORTDRIVER 0x08000000l #define JOY_HWS_ISGAMEPORTBUS 0x80000000l /***************************************************************************** * * Mapping from class strings to class GUIDs. * *****************************************************************************/ typedef struct CLASSMAP { UINT ids; REFGUID rguid; } CLASSMAP, *PCLASSMAP; #pragma BEGIN_CONST_DATA CLASSMAP c_rgcmap[] = { #ifdef DEBUG { IDS_INVALID, &GUID_SysKeyboard, }, /* Bogus class */ #endif { IDS_CLASS_KBD, &GUID_KeyboardClass, }, { IDS_CLASS_MEDIA, &GUID_MediaClass, }, { IDS_CLASS_MOUSE, &GUID_MouseClass, }, { IDS_CLASS_HID, &GUID_HIDClass, }, }; #pragma END_CONST_DATA /***************************************************************************** * * Control panel dialog instance data * * Instance data for control panel dialog box. * *****************************************************************************/ typedef struct TYPENAME { WCHAR wsz[MAX_JOYSTRING]; } TYPENAME, *PTYPENAME; typedef struct CPLDLGINFO { HWND hdlgOwner; /* Owner window */ BOOL fOle; /* Should we create via OLE? */ UINT flCreate; /* Flags */ HWND hwndTypes; /* Listbox for types */ HWND hwndConfigs; /* Listbox for configs */ IDirectInputJoyConfig *pdjc;/* The thing we created */ DARY daryTypes; /* Array of type names */ } CPLDLGINFO, *PCPLDLGINFO; /***************************************************************************** * * Cpl_AddType * *****************************************************************************/ void INTERNAL Cpl_AddType(LPCWSTR pwszType, LPCTSTR ptszName, PCPLDLGINFO pcpl) { int item; item = ListBox_AddString(pcpl->hwndTypes, ptszName); if (item >= 0) { int itype; itype = Dary_Append(&pcpl->daryTypes, (PTYPENAME)0); if (itype >= 0) { PTYPENAME ptype; ptype = Dary_GetPtr(&pcpl->daryTypes, itype, TYPENAME); /* * Must do this because Win95 doesn't have lstrcpyW. */ CopyMemory(ptype->wsz, pwszType, sizeof(WCHAR) * (1 + lstrlenW(pwszType))); ListBox_SetItemData(pcpl->hwndTypes, item, itype); } } } /***************************************************************************** * * Cpl_TypeEnumProc * *****************************************************************************/ BOOL CALLBACK Cpl_TypeEnumProc(LPCWSTR pwszType, LPVOID pvRef) { PCPLDLGINFO pcpl = pvRef; HRESULT hres; DIJOYTYPEINFO jti; jti.dwSize = cbX(jti); hres = pcpl->pdjc->lpVtbl->GetTypeInfo(pcpl->pdjc, pwszType, &jti, DITC_REGHWSETTINGS | DITC_CLSIDCONFIG |DITC_DISPLAYNAME); if (SUCCEEDED(hres)) { TCHAR tsz[MAX_JOYSTRING]; ConvertString(TRUE, jti.wszDisplayName, tsz, cA(tsz)); Cpl_AddType(pwszType, tsz, pcpl); } return DIENUM_CONTINUE; } /***************************************************************************** * * Cpl_OnInitDialog * *****************************************************************************/ BOOL INTERNAL Cpl_OnInitDialog(HWND hdlg, LPARAM lp) { PCPLDLGINFO pcpl = (PV)lp; DIJOYTYPEINFO jti; DIJOYCONFIG jc; int icmap, ijoy; HWND hwnd; HRESULT hres; TCHAR tsz[MAX_JOYSTRING]; SetDialogPtr(hdlg, pcpl); /* * Initialize the list of installable hardware. */ hwnd = GetDlgItem(hdlg, IDC_CPL_CLASSES); for (icmap = 0; icmap < cA(c_rgcmap); icmap++) { int item; LoadString(g_hinst, c_rgcmap[icmap].ids, tsz, cA(tsz)); item = ComboBox_AddString(hwnd, tsz); if (item >= 0) { ComboBox_SetItemData(hwnd, item, icmap); } } ComboBox_SetCurSel(hwnd, 0); /* * Initialize the cooperative level information. */ pcpl->pdjc->lpVtbl->SetCooperativeLevel(pcpl->pdjc, hdlg, DISCL_EXCLUSIVE | DISCL_BACKGROUND); /* * Initialize the list of joystick types. */ pcpl->hwndTypes = GetDlgItem(hdlg, IDC_CPL_TYPES); pcpl->pdjc->lpVtbl->EnumTypes(pcpl->pdjc, Cpl_TypeEnumProc, pcpl); #ifdef DEBUG /* * And add the obligatory invalid item. */ Cpl_AddType(L"", g_tszInvalid, pcpl); #endif /* * Initialize the list of joystick configs. */ pcpl->hwndConfigs = GetDlgItem(hdlg, IDC_CPL_CONFIGS); jc.dwSize = cbX(jc); jti.dwSize = cbX(jti); for (ijoy = 0; ijoy<15; ijoy++) { hres = pcpl->pdjc->lpVtbl->GetConfig(pcpl->pdjc, ijoy, &jc, DIJC_GUIDINSTANCE | DIJC_REGHWCONFIGTYPE ); if (hres == DI_OK) { hres = pcpl->pdjc->lpVtbl->GetTypeInfo(pcpl->pdjc, jc.wszType, &jti, DITC_DISPLAYNAME); if (SUCCEEDED(hres)) { int item; wsprintf(tsz, TEXT("%d (%ls)"), ijoy+1, jti.wszDisplayName); item = ListBox_AddString(pcpl->hwndConfigs, tsz); if (item >= 0) { ListBox_SetItemData(pcpl->hwndConfigs, item, ijoy); } } } } return 1; } ////////////////////////////////////////////////////////// /* #if 0 { HKEY hk; _asm int 3 hres = pcpl->pdjc->lpVtbl->OpenConfigKey(pcpl->pdjc, ijoy, KEY_QUERY_VALUE, &hk); if (SUCCEEDED(hres)) RegCloseKey(hk); } #endif #if 0 jti.dwSize = cbX(jti); jti.hws.dwFlags = 0x12345678; jti.hws.dwNumButtons = 0; CopyMemory(jti.wszDisplayName, L"Fred's Joystick", 2*16); jti.wszCallout[0] = TEXT('\0'); jti.clsidConfig.Data1 = 1; pcpl->pdjc->lpVtbl->Acquire(pcpl->pdjc); // pcpl->pdjc->lpVtbl->SetTypeInfo(pcpl->pdjc, L"Fred", &jti, DITC_CLSIDCONFIG); pcpl->pdjc->lpVtbl->SendNotify(pcpl->pdjc); // pcpl->pdjc->lpVtbl->Unacquire(pcpl->pdjc); #endif #if 0 // memset(&jc, 0xCC, cbX(jc)); jc.dwSize = cbX(jc); pcpl->pdjc->lpVtbl->GetConfig(pcpl->pdjc, 0, &jc, DIJC_GUIDINSTANCE | DIJC_REGHWCONFIGTYPE | //DIJC_GAIN | 0);//DIJC_CALLOUT); tsz; #if 0 // HACKHACK NT wsprintf(tsz, "GUID=%08x, Flags=%08x, buttons=%d gain=%d type=%ls\r\n", jc.guidInstance.Data1, jc.hwc.hws.dwFlags, jc.hwc.hws.dwNumButtons, jc.dwGain, jc.wszType); OutputDebugString(tsz); #endif pcpl->pdjc->lpVtbl->Acquire(pcpl->pdjc); // MultiByteToWideChar(CP_ACP, 0, "#3", -1, jc.wszType, MAX_JOYSTRING); jc.dwGain = 5000; // pcpl->pdjc->lpVtbl->SetConfig(pcpl->pdjc, 0, &jc, DIJC_GAIN); pcpl->pdjc->lpVtbl->Unacquire(pcpl->pdjc); #endif */ //////////////////////////////////////////////////////////////////////////////// /***************************************************************************** * * Cpl_OnAddNewHardware * *****************************************************************************/ BOOL INTERNAL Cpl_OnAddNewHardware(HWND hdlg) { PCPLDLGINFO pcpl = GetDialogPtr(hdlg); HWND hwnd = GetDlgItem(hdlg, IDC_CPL_CLASSES); int item; int icmap; if ((item = (int)ComboBox_GetCurSel(hwnd)) >= 0 && (icmap = (int)ComboBox_GetItemData(hwnd, item)) >= 0) { HRESULT hres; hres = pcpl->pdjc->lpVtbl->AddNewHardware( pcpl->pdjc, hdlg, c_rgcmap[icmap].rguid); if (SUCCEEDED(hres)) { } else if (hres == DIERR_CANCELLED) { } else { MessageBoxV(hdlg, IDS_ERR_ADDNEWHARDWARE, hres); } } return TRUE; } /***************************************************************************** * * Cpl_OnTypeDblClk * * An item in the types list box was double-clicked. Display details. * *****************************************************************************/ BOOL INTERNAL Cpl_OnTypeDblClk(HWND hdlg) { PCPLDLGINFO pcpl = GetDialogPtr(hdlg); int iItem; iItem = ListBox_GetCurSel(pcpl->hwndTypes); if (iItem >= 0) { int itype = (int)ListBox_GetItemData(pcpl->hwndTypes, iItem); if (itype >= 0) { PTYPENAME ptype = Dary_GetPtr(&pcpl->daryTypes, itype, TYPENAME); Type_Create(hdlg, pcpl->pdjc, ptype->wsz); } /* * That dialog screws up the vwi state. */ SetActiveWindow(hdlg); } return 1; } /***************************************************************************** * * Cpl_GetFirstFreeID * *****************************************************************************/ int INTERNAL Cpl_GetFirstFreeID(HWND hdlg) { PCPLDLGINFO pcpl = GetDialogPtr(hdlg); int ijoy; DIJOYCONFIG jc; HRESULT hres; jc.dwSize = cbX(jc); for (ijoy = 0; ijoy < 15; ijoy++ ){ hres = pcpl->pdjc->lpVtbl->GetConfig(pcpl->pdjc, ijoy, &jc, DIJC_GUIDINSTANCE | DIJC_REGHWCONFIGTYPE ); if (hres != DI_OK) { break; } } return ijoy; } /***************************************************************************** * * Cpl_AddSelectedItem * *****************************************************************************/ GUID GUID_GAMEENUM_BUS_ENUMERATOR2 = {0xcae56030, 0x684a, 0x11d0, 0xd6, 0xf6, 0x00, 0xa0, 0xc9, 0x0f, 0x57, 0xda}; BOOL INTERNAL Cpl_AddSelectedItem( HWND hdlg, DIJOYTYPEINFO *pjti, DWORD dwType, PTYPENAME ptype ) { PCPLDLGINFO pcpl = GetDialogPtr(hdlg); DIJOYTYPEINFO jti; DIJOYCONFIG jc; int ijoy; TCHAR tsz[MAX_JOYSTRING]; HRESULT hres; BOOL bRet = FALSE; ijoy = Cpl_GetFirstFreeID(hdlg); if ( ijoy >= 15 ) { #ifdef _DEBUG OutputDebugString(TEXT("No available ID to SetConfig.\n")); #endif return FALSE; } memset( &jc, 0, cbX(jc) ); jc.dwSize = cbX(DIJOYCONFIG); jc.hwc.hws = pjti->hws; jc.hwc.hws.dwFlags |= JOY_HWS_ISANALOGPORTDRIVER; jc.hwc.dwUsageSettings |= JOY_US_PRESENT; jc.hwc.dwType = dwType; lstrcpyW(jc.wszCallout, pjti->wszCallout); lstrcpyW(jc.wszType, ptype->wsz); jc.guidGameport = GUID_GAMEENUM_BUS_ENUMERATOR2; if ( SUCCEEDED(pcpl->pdjc->lpVtbl->Acquire(pcpl->pdjc)) ) { hres = pcpl->pdjc->lpVtbl->SetConfig(pcpl->pdjc, ijoy, &jc, DIJC_REGHWCONFIGTYPE | DIJC_CALLOUT | DIJC_WDMGAMEPORT); if ( SUCCEEDED(hres) ) { bRet = TRUE; } else { #ifdef DEBUG OutputDebugString(TEXT("SetConfig failed.\n")); #endif goto _done; } ZeroX(jc); ZeroX(jti); jc.dwSize = cbX(jc); jti.dwSize = cbX(jti); hres = pcpl->pdjc->lpVtbl->GetConfig(pcpl->pdjc, ijoy, &jc, DIJC_GUIDINSTANCE | DIJC_REGHWCONFIGTYPE ); if (hres == DI_OK) { hres = pcpl->pdjc->lpVtbl->GetTypeInfo(pcpl->pdjc, jc.wszType, &jti, DITC_DISPLAYNAME); if (SUCCEEDED(hres)) { int item; wsprintf(tsz, TEXT("%d (%ls)"), ijoy+1, jti.wszDisplayName); item = ListBox_AddString(pcpl->hwndConfigs, tsz); if (item >= 0) { ListBox_SetItemData(pcpl->hwndConfigs, item, ijoy); } } } pcpl->pdjc->lpVtbl->Unacquire(pcpl->pdjc); pcpl->pdjc->lpVtbl->SendNotify(pcpl->pdjc); } _done: return bRet; } /***************************************************************************** * * Cpl_AddJoystick * * The joystick selected in the types list box is added. * *****************************************************************************/ BOOL INTERNAL Cpl_AddJoystick(HWND hdlg) { PCPLDLGINFO pcpl = GetDialogPtr(hdlg); int iItem; BOOL bRet = FALSE; iItem = ListBox_GetCurSel(pcpl->hwndTypes); if (iItem >= 0) { int itype = (int)ListBox_GetItemData(pcpl->hwndTypes, iItem); if (itype >= 0) { PTYPENAME ptype = Dary_GetPtr(&pcpl->daryTypes, itype, TYPENAME); DIJOYTYPEINFO jti; HRESULT hres; jti.dwSize = cbX(jti); hres = pcpl->pdjc->lpVtbl->GetTypeInfo(pcpl->pdjc, ptype->wsz, &jti, DITC_REGHWSETTINGS | DITC_DISPLAYNAME); if (SUCCEEDED(hres)) { bRet = Cpl_AddSelectedItem( hdlg, &jti, iItem, ptype ); } } SetActiveWindow(hdlg); } return bRet; } /***************************************************************************** * * Cpl_DeleteSelectedItem * *****************************************************************************/ BOOL INTERNAL Cpl_DeleteSelectedItem( HWND hdlg, int iItem, int iJoy ) { PCPLDLGINFO pcpl = GetDialogPtr(hdlg); HRESULT hres; BOOL bRet = FALSE; hres = pcpl->pdjc->lpVtbl->Acquire(pcpl->pdjc); if(SUCCEEDED(hres)) { hres = pcpl->pdjc->lpVtbl->DeleteConfig(pcpl->pdjc, iJoy); if(SUCCEEDED(hres)) { pcpl->pdjc->lpVtbl->SendNotify(pcpl->pdjc); ListBox_DeleteString(pcpl->hwndConfigs, iItem); pcpl->pdjc->lpVtbl->Unacquire(pcpl->pdjc); bRet = TRUE; } } return bRet; } /***************************************************************************** * * Cpl_DeleteJoystick * * The joystick selected in the types list box is added. * *****************************************************************************/ BOOL INTERNAL Cpl_DeleteJoystick(HWND hdlg) { PCPLDLGINFO pcpl = GetDialogPtr(hdlg); int iItem; BOOL bRet = FALSE; iItem = ListBox_GetCurSel(pcpl->hwndConfigs); if (iItem >= 0) { int iJoy = (int)ListBox_GetItemData(pcpl->hwndConfigs, iItem); if (iJoy >= 0) { bRet = Cpl_DeleteSelectedItem( hdlg, iItem, iJoy ); } SetActiveWindow(hdlg); } return bRet; } /***************************************************************************** * * Cpl_OnUserValues * * Open the User Values dialog. * *****************************************************************************/ BOOL INTERNAL Cpl_OnUserValues(HWND hdlg) { PCPLDLGINFO pcpl = GetDialogPtr(hdlg); Uv_Create(hdlg, pcpl->pdjc); return 1; } /***************************************************************************** * * Cpl_OnCommand * *****************************************************************************/ BOOL INTERNAL Cpl_OnCommand(HWND hdlg, int id, UINT cmd) { switch (id) { case IDC_CPL_ADD: return Cpl_OnAddNewHardware(hdlg); case IDC_CPL_TYPES: if (cmd == LBN_DBLCLK) { return Cpl_OnTypeDblClk(hdlg); } break; case IDC_CPL_ADDJOYSTICK: if (cmd == BN_CLICKED) { return Cpl_AddJoystick(hdlg); } break; case IDC_CPL_DELJOYSTICK: if (cmd == BN_CLICKED) { return Cpl_DeleteJoystick(hdlg); } break; case IDC_CPL_USERVALUES: if (cmd == BN_CLICKED) { return Cpl_OnUserValues(hdlg); } break; } return 0; } /***************************************************************************** * * Cpl_DlgProc * *****************************************************************************/ INT_PTR INTERNAL Cpl_DlgProc(HWND hdlg, UINT wm, WPARAM wp, LPARAM lp) { switch (wm) { case WM_INITDIALOG: return Cpl_OnInitDialog(hdlg, lp); case WM_DESTROY: /* * Cpl_ThreadStart will do the cleanup for us. */ break; case WM_COMMAND: return Cpl_OnCommand(hdlg, (int)GET_WM_COMMAND_ID(wp, lp), (UINT)GET_WM_COMMAND_CMD(wp, lp)); case WM_CLOSE: DestroyWindow(hdlg); return TRUE; } return 0; } /***************************************************************************** * * Cpl_DoCpl * *****************************************************************************/ void INLINE Cpl_DoCpl(PCPLDLGINFO pcpl) { SendNotifyMessage(pcpl->hdlgOwner, WM_THREADSTARTED, 0, 0); /* * This function also sends the WM_CHILDEXIT. */ SemimodalDialogBoxParam(IDD_CPL, pcpl->hdlgOwner, Cpl_DlgProc, (LPARAM)pcpl); } /***************************************************************************** * * Cpl_ThreadStart * * Runs on the new thread. Creates the object and spins the dialog * box to control it. * *****************************************************************************/ DWORD WINAPI Cpl_ThreadStart(PCPLDLGINFO pcpl) { HRESULT hres; LPDIRECTINPUTA pdia; hres = CoInitialize(0); if (SUCCEEDED(hres)) { hres = CreateDI(pcpl->fOle, pcpl->flCreate, (PPV)&pdia); if (SUCCEEDED(hres)) { hres = IDirectInput_QueryInterface(pdia, &IID_IDirectInputJoyConfig, (PV)&pcpl->pdjc); if (SUCCEEDED(hres)) { Cpl_DoCpl(pcpl); if( pcpl->pdjc ) IDirectInputJoyConfig_Release(pcpl->pdjc); } else { ThreadFailHres(pcpl->hdlgOwner, IDS_ERR_QICONFIG, hres); } pdia->lpVtbl->Release(pdia); } else { ThreadFailHres(pcpl->hdlgOwner, IDS_ERR_CREATEOBJ, hres); } CoUninitialize(); } else { ThreadFailHres(pcpl->hdlgOwner, IDS_ERR_COINIT, hres); } Dary_Term(&pcpl->daryTypes); LocalFree(pcpl); return 0; } /***************************************************************************** * * Cpl_Create * * Spin a thread to create a DirectInput device interface. * *****************************************************************************/ INT_PTR EXTERNAL Cpl_Create(HWND hdlg, BOOL fOle, UINT flCreate) { PCPLDLGINFO pcpl = LocalAlloc(LPTR, cbX(CPLDLGINFO)); if (pcpl) { DWORD id; HANDLE h; pcpl->hdlgOwner = hdlg ; pcpl->fOle = fOle ; pcpl->flCreate = flCreate ; h = CreateThread(0, 0, Cpl_ThreadStart, pcpl, 0, &id); if (h) { ; } else { LocalFree(pcpl); pcpl = 0; } } return (INT_PTR)pcpl; }