// Eigenschaftsseiten-Lieferant für USB2LPT im Gerätemanager // Übersetzbar mit Borland C++ 3.1 #define NONAMELESSUNION #define STRICT //#include "wutils.h" #include // strtoul #include // _fmemcmp #include #include // Message Cracker #include #include #include #include // EXTERN_C, benötigt _fmemcmp #include // DEFINE_GUID, benötigt EXTERN_C #include "usb2lpt.h" #include #include "thunk16.h" #define CTL_CODE(DeviceType,Function,Method,Access) \ (((DWORD)(DeviceType)<<16)|((Access)<<14)|((Function)<<2)|(Method)) #define FILE_DEVICE_UNKNOWN 0x22 #define METHOD_BUFFERED 0 //#define METHOD_IN_DIRECT 1 //#define METHOD_OUT_DIRECT 2 //#define METHOD_NEITHER 3 #define FILE_ANY_ACCESS 0 typedef char TCHAR; typedef unsigned long ULONG,FAR*LPULONG,NEAR*NPULONG,*PULONG; typedef UINT *PUINT,NEAR*NPUINT,FAR*LPUINT; typedef const TCHAR *PCTSTR,NEAR*NPCTSTR,FAR*LPCTSTR; #define TEXT(x) x #define nobreak typedef enum {false,true} bool; #define hInst (HINSTANCE)_DS typedef struct{ BYTE usage; // Benutzungszähler, für 2 Dialoge BYTE wizard; // Install-Wizard aktiv TUserCfg uc; // Konfiguration für Treiber (3 WORDs) TAccessCnt ac; // Zugriffszähler aus Treiber (6 DWORDs) DWORD kernel32; // Geladene 32-bit-DLL DWORD dev; // Griff zum .SYS-Treiber HFONT bold,italic; // Für hübscheren Dialog, fette und kursive Schrift LPDEVICE_INFO info; // brauchen wir zz. nicht: SetupDi==Holzweg! }TSetup,*PSetup,FAR*LPSetup,NEAR*NPSetup; TCHAR MBoxTitle[64]; /********************************************* * Hilfsfunktionen, vornehmlich aus WUTILS.C * *********************************************/ int vMBox(HWND Wnd, UINT id, UINT style, va_list arglist) { TCHAR buf1[256],buf2[256]; LoadString(hInst,id,buf1,elemof(buf1)); wvsprintf(buf2,buf1,arglist); return MessageBox(Wnd,buf2,MBoxTitle,style); } int _cdecl MBox(HWND Wnd, UINT id, UINT style,...) { return vMBox(Wnd,id,style,(va_list)(&style+1)); } UINT GetComboHex(HWND Wnd) { // Liefert Hex-Wert oder 0 bei Fehler TCHAR s[20]; GetWindowText(Wnd,s,elemof(s)); return (UINT)strtol(s,NULL,16); } UINT GetCheckboxGroup(HWND Wnd, UINT u, UINT o) { UINT v,m; for (v=0,m=1; u<=o; u++,m+=m) if (IsDlgButtonChecked(Wnd,u)==1) v|=m; return v; } void SetCheckboxGroup(HWND Wnd, UINT u, UINT o, UINT v) { for (; u<=o; u++,v>>=1) CheckDlgButton(Wnd,u,v&1); } void ChangeFonts(HWND w) { /* Macht alle eingeklammerten () statischen Texte kursiv und * Überschriften von Gruppenfenstern fett; der besseren Übersicht wegen. * Fonts werden neu erzeugt, wenn die entspr. Felder in TSetup NULL sind. * Diese beiden Fonts müssen beim Beenden freigegeben werden! */ HFONT normal; LOGFONT font; PSetup S=(PSetup)GetWindowLong(w,DWL_USER); normal=GetWindowFont(w); if (!S->italic) { GetObject(normal,sizeof(font),&font); font.lfItalic=TRUE; S->italic=CreateFontIndirect(&font); } if (!S->bold) { GetObject(normal,sizeof(font),&font); font.lfWeight=700; S->bold=CreateFontIndirect(&font); } for (w=GetWindow(w,GW_CHILD);w;w=GetNextSibling(w)) { TCHAR s[2],cl[10]; // reicht für das erste Zeichen GetClassName(w,cl,elemof(cl)); if (!lstrcmpi(cl,T("STATIC"))) { GetWindowText(w,s,elemof(s)); if (s[0]=='(') SetWindowFont(w,S->italic,TRUE); } if (!lstrcmpi(cl,T("BUTTON"))) { if ((GetWindowStyle(w)&0x0F) == BS_GROUPBOX) SetWindowFont(w,S->bold,TRUE); } } } /********************************************** * Dialogprozedur: Lese-Cache-Feineinstellung * **********************************************/ BOOL CALLBACK _loadds ExtraDlgProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) { PSetup S=(PSetup)GetWindowLong(Wnd,DWL_USER); switch (Msg) { case WM_INITDIALOG: { S=(PSetup)lParam; SetWindowLong(Wnd,DWL_USER,lParam); SetCheckboxGroup(Wnd,20,22,S->uc.flags>>UCB_ReadCache0); }return TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: { S->uc.flags&=~(7<uc.flags|=GetCheckboxGroup(Wnd,20,22)<dev) return true; // Ist schon offen! cfgmgr32=LoadLibraryEx32W("cfgmgr32.dll",0,0); if (!cfgmgr32) return false; ok=(bool)(lpGetDevID=GetProcAddress32W(cfgmgr32,"CM_Get_Device_IDA")) && (bool)(lpGetDevIF=GetProcAddress32W(cfgmgr32,"CM_Get_Device_Interface_ListA")) && !CallProcEx32W(4,2,lpGetDevID,S->info->dnDevnode,(LPSTR)k,(DWORD)sizeof(k),0L) && !CallProcEx32W(5,7,lpGetDevIF,(LPGUID)&Vlpt_GUID,(LPSTR)k,(LPSTR)n,(DWORD)sizeof(n),0L); FreeLibrary32W(cfgmgr32); if (!ok) return false; S->kernel32=LoadLibraryEx32W("kernel32.dll",0,0); if (!S->kernel32) return false; lpCreateFile=GetProcAddress32W(S->kernel32,"CreateFileA"); if (!lpCreateFile) return false; S->dev=CallProcEx32W(7,1,lpCreateFile, (LPSTR)n,0xC0000000L,0L,(DWORD)NULL,3L/*OPEN_EXISTING*/,0L,0L); if (S->dev==(DWORD)-1) { S->dev=0; // wegen von Unix geerbter Win32-Macke! return false; } return true; } long DevIoctl(PSetup S,DWORD code,LPVOID p1,long l1,LPVOID p2,long l2) { long ret=-1; if (S->dev) { DWORD lpDeviceIoControl=GetProcAddress32W(S->kernel32,"DeviceIoControl"); if (lpDeviceIoControl) CallProcEx32W(8,0x54,lpDeviceIoControl, S->dev,code,p1,l1,p2,l2,(LPVOID)&ret,0L); } return ret; } void CloseDev(PSetup S) { if (S->kernel32 && S->dev) { DWORD lpCloseHandle=GetProcAddress32W(S->kernel32,"CloseHandle"); if (lpCloseHandle) CallProcEx32W(1,0,lpCloseHandle,S->dev); S->dev=0; } if (S->kernel32) FreeLibrary32W(S->kernel32); S->kernel32=0; } /************************************************ * Eigenschaftsseiten-Dialogprozedur: Emulation * ************************************************/ void CheckButton13(HWND Wnd, PSetup S) { UINT i=2; switch ((S->uc.flags>>UCB_ReadCache0) &7) { case 0: i--; nobreak;// i=0 case 7: i--; // i=1 } CheckDlgButton(Wnd,13,i); } BOOL CALLBACK _loadds EmulDlgProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) { static const WORD DefLpt[]={0x378,0x278,0x3BC}; PSetup S=(PSetup)GetWindowLong(Wnd,DWL_USER); switch (Msg) { case WM_INITDIALOG: { static const TCHAR LptStd[]=T("LPT1\0LPT2\0LPT1 anno 1985\0"); static const TCHAR LptEnh[]=T("SPP\0EPP 1.9\0ECP\0ECP + EPP\0"); PCTSTR p; TCHAR s[32]; HWND w0,w2; int i; S=(PSetup)((LPPROPSHEETPAGE)lParam)->lParam; SetWindowLong(Wnd,DWL_USER,(LONG)S); ChangeFonts(Wnd); w0=GetDlgItem(Wnd,100); // Adresse for (p=LptStd,i=0;*p;p+=lstrlen(p)+1,i++) { wsprintf(s,T("%Xh (%u, %s)"),DefLpt[i],DefLpt[i],(LPCSTR)p); (void)ComboBox_AddString(w0,s); } w2=GetDlgItem(Wnd,102); // Parallelport-Erweiterung for (p=LptEnh;*p;p+=lstrlen(p)+1) (void)ComboBox_AddString(w2,p); if (OpenDev(S)) { DevIoctl(S,IOCTL_VLPT_UserCfg,&S->uc,0,&S->uc,sizeof(TUserCfg)); CloseDev(S); }else{ // Werte aus Registry holen, wie?? MessageBeep(MB_ICONHAND); } for (i=0; i<3; i++) if (S->uc.LptBase==DefLpt[i]) { (void)ComboBox_SetCurSel(w0,i); goto skip; } wsprintf(s,T("%Xh"),S->uc.LptBase); SetWindowText(w0,s); skip: (void)ComboBox_SetCurSel(w2,S->uc.Mode); SetCheckboxGroup(Wnd,10,12,S->uc.flags>>UCB_Debugreg); SetDlgItemInt(Wnd,101,S->uc.TimeOut,FALSE); SendMessage(Wnd,WM_COMMAND,12,0); CheckButton13(Wnd,S); /* DWORD length=sizeof(s); HKEY key; key=SetupDiOpenDevRegKey(stuff->info,stuff->sdd,DICS_FLAG_GLOBAL,0,DIREG_DEV,KEY_READ); if (key) { if (!RegQueryValueEx(key,T("Portadresse"),NULL,NULL,(LPBYTE)s,&length)) { MessageBeep(0); DoEnvironmentSubst(s,sizeof(s)); } RegCloseKey(key); } // get sample info URL */ }return TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { case 12: EnableWindow(GetDlgItem(Wnd,101),IsDlgButtonChecked(Wnd,12)); break; case 13: switch (IsDlgButtonChecked(Wnd,13)) { case 2: CheckDlgButton(Wnd,13,0); nobreak; // 3. Zustand nicht klickbar! case 0: S->uc.flags&=~(7<uc.flags|=7<code){ case PSN_KILLACTIVE: { // Überprüfung der Eingabefelder! HWND w; UINT u; BOOL Ok; //--- w=GetDlgItem(Wnd,100); u=GetComboHex(w); if (!u) { MBox(Wnd,17,MB_OK|MB_ICONEXCLAMATION); goto f1; } if (u<0x100 || u&3 || u>>16 // gewöhnliche Fehler || u==0x1E0 || u==0x1E4 || u==0x1F0 || u==0x1F4 || u==0x3E4 || u==0x3F4) { MBox(Wnd,18,MB_OK|MB_ICONEXCLAMATION); f1: SetFocus(w); // Festplattenports vor DAU schützen!! (void)ComboBox_SetEditSel(w,0,(UINT)-1); goto fail; } S->uc.LptBase=(WORD)u; //--- w=GetDlgItem(Wnd,102); u=ComboBox_GetCurSel(w); if (u&1 && S->uc.LptBase&7) {// EPP geht nur mit durch 8 teilbaren Adressen! MBox(Wnd,19,MB_OK|MB_ICONEXCLAMATION); SetFocus(w); goto fail; } S->uc.Mode=(BYTE)u; //--- if (!S->wizard) { w=GetDlgItem(Wnd,101); u=GetDlgItemInt(Wnd,101,&Ok,FALSE); if (!Ok || u>1000) { MBox(Wnd,20,MB_OK|MB_ICONEXCLAMATION); SetFocus(w); Edit_SetSel(w,0,(UINT)-1); goto fail; } S->uc.TimeOut=(WORD)u; //--- S->uc.flags&=~(7<uc.flags|=GetCheckboxGroup(Wnd,10,12)<uc.LptBase) goto setit; if (MBox(Wnd,16,MB_YESNO,S->uc.LptBase)!=IDYES) { SetWindowLong(Wnd,DWL_MSGRESULT,PSNRET_INVALID); return TRUE; } setit: if (OpenDev(S)) { DevIoctl(S,IOCTL_VLPT_UserCfg,&S->uc,sizeof(TUserCfg),&S->uc,0); CloseDev(S); }else{ // Meckern?? MessageBeep(MB_ICONHAND); }break; } } } return FALSE; } void UpdateEditArray(HWND Wnd, UINT u, UINT o, ULONG*old, ULONG _ss*n) { for (;u<=o;u++,old++,n++) { if (*old!=*n) { char s[32]; wsprintf(s,T("%lu"),(*old=*n)); SetDlgItemText(Wnd,u,s); } } } BOOL CALLBACK _loadds StatDlgProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) { PSetup S=(PSetup)GetWindowLong(Wnd,DWL_USER); switch (Msg) { case WM_INITDIALOG: { S=(PSetup)((LPPROPSHEETPAGE)lParam)->lParam; SetWindowLong(Wnd,DWL_USER,(LONG)S); ChangeFonts(Wnd); S->ac.out=S->ac.in=S->ac.fail=S->ac.steal=S->ac.wpu=S->ac.rpu=(ULONG)-1; SendMessage(Wnd,WM_TIMER,0,0); }return TRUE; case WM_TIMER: if (OpenDev(S)) { // bleibt normalerweise geöffnet TAccessCnt AC; if (DevIoctl(S,IOCTL_VLPT_AccessCnt,&AC,0,&AC,sizeof(AC))!=-1) UpdateEditArray(Wnd,100,105,&S->ac.out,&AC.out); }break; case WM_COMMAND: switch (LOWORD(wParam)) { case 106: S->ac.out=S->ac.in=S->ac.fail=S->ac.steal=0; goto weiter; case 107: S->ac.wpu=S->ac.rpu=0; weiter: { if (!OpenDev(S)) break; if (DevIoctl(S,IOCTL_VLPT_AccessCnt,&S->ac,sizeof(S->ac),&S->ac,0)==1) MessageBeep(MB_ICONEXCLAMATION); } }break; case WM_NOTIFY: switch (((LPNMHDR)lParam)->code){ case PSN_SETACTIVE: { SetTimer(Wnd,100,500,NULL); }break; case PSN_KILLACTIVE: { KillTimer(Wnd,100); CloseDev(S); }break; }break; } return FALSE; } #pragma argsused UINT CALLBACK _loadds PageCallbackProc(HWND Wnd, UINT Msg, LPPROPSHEETPAGE p) { PSetup S=(PSetup)p->lParam; if (S) switch (Msg) { case PSPCB_CREATE: S->usage++; break; case PSPCB_RELEASE: if (!(--S->usage)) { CloseDev(S); if (S->italic)DeleteFont(S->italic); if (S->bold) DeleteFont(S->bold); LocalFree((HLOCAL)S); // free(S); p->lParam=0; } } return TRUE; } UINT InitStruct(void far*buf, unsigned len) { _fmemset(buf,0,len); *(unsigned far*)buf=len; return 0; } EXTERN_C BOOL CALLBACK _loadds EnumPropPages(LPDEVICE_INFO lpdi, LPFNADDPROPSHEETPAGE AddPage, LPARAM lParam) { HPROPSHEETPAGE hpage; NPSetup S; // PSetup S=new TSetup; PROPSHEETPAGE page; // _asm int 3; S=(PSetup)LocalAlloc(LPTR,sizeof(TSetup)); // Ohne HEAPSIZE in der prop16.def hängt LocalAlloc den Prozess auf! // S=(PSetup)malloc(sizeof(TSetup)); InitStruct(&page,sizeof(page)); LOWORD(page.dwFlags)=PSP_USECALLBACK; page.hInstance=hInst; LOWORD(page.DUMMYUNIONNAME.pszTemplate)=100; page.pfnDlgProc=EmulDlgProc; page.lParam=(LPARAM)S; page.pfnCallback=PageCallbackProc; S->info=lpdi; lstrcpy(MBoxTitle,lpdi->szDescription); hpage=CreatePropertySheetPage(&page); if (!AddPage(hpage,lParam)) DestroyPropertySheetPage(hpage); page.DUMMYUNIONNAME.pszTemplate++; page.pfnDlgProc=StatDlgProc; hpage=CreatePropertySheetPage(&page); if (!AddPage(hpage,lParam)) DestroyPropertySheetPage(hpage); return TRUE; } #pragma argsused EXTERN_C DWORD CALLBACK _loadds CoDeviceInstall( UINT InstallFunction, LPDEVICE_INFO DeviceInfoData, /*PCOINSTALLER_CONTEXT_DATA*/long Context) { _asm int 3; #if 0 switch (InstallFunction) { case DIF_NEWDEVICEWIZARD_FINISHINSTALL: { SP_NEWDEVICEWIZARD_DATA NDWD; PSetup S=(PSetup)LocalAlloc(LPTR,sizeof(TSetup)); PROPSHEETPAGE page={ sizeof(PROPSHEETPAGE), PSP_USECALLBACK|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE, hInst, //nicht-statisch MAKEINTRESOURCE(103), 0, // Icon NULL, // Titel EmulDlgProc, (LPARAM)S, //nicht-statisch PageCallbackProc, NULL, //pcRefParent MAKEINTRESOURCE(21),// erfordert (irgendwo) ein #define _WIN32_IE 0x0500 MAKEINTRESOURCE(22)}; S->wizard=TRUE; S->info=DeviceInfoSet; S->sdd= DeviceInfoData; NDWD.ClassInstallHeader.cbSize=sizeof(SP_CLASSINSTALL_HEADER); NDWD.ClassInstallHeader.InstallFunction=DIF_ADDPROPERTYPAGE_ADVANCED; if (SetupDiGetClassInstallParams(DeviceInfoSet,DeviceInfoData, &NDWD.ClassInstallHeader,sizeof(NDWD),NULL) && NDWD.NumDynamicPages < MAX_INSTALLWIZARD_DYNAPAGES) { NDWD.DynamicPages[NDWD.NumDynamicPages++]= CreatePropertySheetPage(&page); SetupDiSetClassInstallParams(DeviceInfoSet,DeviceInfoData, &NDWD.ClassInstallHeader,sizeof(NDWD)); }else{ MessageBeep(MB_ICONEXCLAMATION); LocalFree(S); } }break; } #endif return 0/*NO_ERROR*/; } #pragma argsused EXTERN_C int CALLBACK LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine) { return TRUE; }