Implemented serialui dll containing CommConfigDialog,
GetDefaultCommConfig and SetDefaultCommConfig.
diff --git a/Make.rules.in b/Make.rules.in
index de70b81..0fa344f 100644
--- a/Make.rules.in
+++ b/Make.rules.in
@@ -132,6 +132,7 @@
rasapi32 \
riched32 \
rpcrt4 \
+ serialui \
setupapi \
setupx \
shell32 \
diff --git a/configure b/configure
index 25880d3..349606f 100755
--- a/configure
+++ b/configure
@@ -6210,6 +6210,7 @@
dlls/rasapi32/Makefile
dlls/richedit/Makefile
dlls/rpcrt4/Makefile
+dlls/serialui/Makefile
dlls/setupapi/Makefile
dlls/setupx/Makefile
dlls/shell32/Makefile
@@ -6450,6 +6451,7 @@
dlls/rasapi32/Makefile
dlls/richedit/Makefile
dlls/rpcrt4/Makefile
+dlls/serialui/Makefile
dlls/setupapi/Makefile
dlls/setupx/Makefile
dlls/shell32/Makefile
diff --git a/configure.in b/configure.in
index aad7852..0712872 100644
--- a/configure.in
+++ b/configure.in
@@ -1009,6 +1009,7 @@
dlls/rasapi32/Makefile
dlls/richedit/Makefile
dlls/rpcrt4/Makefile
+dlls/serialui/Makefile
dlls/setupapi/Makefile
dlls/setupx/Makefile
dlls/shell32/Makefile
diff --git a/dlls/Makefile.in b/dlls/Makefile.in
index a7c8d49..f554ef2 100644
--- a/dlls/Makefile.in
+++ b/dlls/Makefile.in
@@ -44,6 +44,7 @@
rasapi32/librasapi32.@LIBEXT@ \
richedit/libriched32.@LIBEXT@ \
rpcrt4/librpcrt4.@LIBEXT@ \
+ serialui/libserialui.@LIBEXT@ \
setupx/libsetupx.@LIBEXT@ \
setupapi/libsetupapi.@LIBEXT@ \
shell32/libshell32.@LIBEXT@ \
@@ -150,6 +151,7 @@
rasapi32 \
richedit \
rpcrt4 \
+ serialui \
setupx \
shell32 \
shfolder \
@@ -304,6 +306,9 @@
librpcrt4.@LIBEXT@: rpcrt4/librpcrt4.@LIBEXT@
$(RM) $@ && $(LN_S) rpcrt4/librpcrt4.@LIBEXT@ $@
+libserialui.@LIBEXT@: serialui/libserialui.@LIBEXT@
+ $(RM) $@ && $(LN_S) serialui/libserialui.@LIBEXT@ $@
+
libsetupapi.@LIBEXT@: setupapi/libsetupapi.@LIBEXT@
$(RM) $@ && $(LN_S) setupapi/libsetupapi.@LIBEXT@ $@
diff --git a/dlls/serialui/.cvsignore b/dlls/serialui/.cvsignore
new file mode 100644
index 0000000..ce9997d
--- /dev/null
+++ b/dlls/serialui/.cvsignore
@@ -0,0 +1,4 @@
+Makefile
+libserialui.so.1.0
+serialui.spec.c
+serialui_rc.s
diff --git a/dlls/serialui/Makefile.in b/dlls/serialui/Makefile.in
new file mode 100644
index 0000000..3139dda
--- /dev/null
+++ b/dlls/serialui/Makefile.in
@@ -0,0 +1,16 @@
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR = @srcdir@
+VPATH = @srcdir@
+MODULE = serialui
+SOVERSION = 1.0
+
+C_SRCS = \
+ confdlg.c
+
+RC_SRCS= \
+ serialui_rc.rc
+
+@MAKE_DLL_RULES@
+
+### Dependencies:
diff --git a/dlls/serialui/confdlg.c b/dlls/serialui/confdlg.c
new file mode 100644
index 0000000..63479c4
--- /dev/null
+++ b/dlls/serialui/confdlg.c
@@ -0,0 +1,543 @@
+/*
+ * This DLL contains the user interface for the serial driver.
+ * a Dialog box to configure the specified COMM port
+ * an interface to the control panel (??)
+ * functions to load and save default configuration
+ *
+ * Eventually the 32 bit comm port driver could be moved into here
+ * and interfaced to KERNEL32 using the WIN95 or WINNT comm driver interface.
+ * This way, different driver DLLS could be written to support other
+ * serial interfaces, such as X.25, etc.
+ *
+ * Basic structure copied from COMCTL32 code.
+ *
+ * Copyright 2000 Mike McCormack
+ */
+
+#include <string.h>
+
+#include "winbase.h"
+#include "winreg.h"
+#include "dialog.h"
+#include "win.h"
+#include "debugtools.h"
+#include "serialui.h"
+#include "winerror.h"
+
+#include "queue.h"
+#include "message.h"
+
+DEFAULT_DEBUG_CHANNEL(comm)
+
+HMODULE SERIALUI_hModule = 0;
+DWORD SERIALUI_dwProcessesAttached = 0;
+
+/***********************************************************************
+ * SERIALUI_LibMain [Internal] Initializes the internal 'SERIALUI.DLL'.
+ *
+ * PARAMS
+ * hinstDLL [I] handle to the 'dlls' instance
+ * fdwReason [I]
+ * lpvReserved [I] reserverd, must be NULL
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ */
+
+BOOL WINAPI
+SERIALUI_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
+
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ if (SERIALUI_dwProcessesAttached == 0) {
+
+ /* This will be wrong for any other process attching in this address-space! */
+ SERIALUI_hModule = (HMODULE)hinstDLL;
+
+ }
+ SERIALUI_dwProcessesAttached++;
+ break;
+
+ case DLL_PROCESS_DETACH:
+ SERIALUI_dwProcessesAttached--;
+ if (SERIALUI_dwProcessesAttached == 0) {
+ TRACE("Last Process detached\n");
+ }
+ break;
+ }
+
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * SERIALUI_EnumPropPages (SERIALUI.2)
+ *
+ * Called by the device manager to add prop sheets in Control Panel ???
+ * Pointed to in Win98 registry by
+ * \System\CurrentControlSet\Services\Class\ports\0000\EnumPropPages =
+ * "serialui.dll,EnumPropPages"
+ */
+typedef LPVOID LPDEVICE_INFO;
+typedef LPVOID LPFNADDPROPSHEETPAGE;
+BOOL WINAPI SERIALUI_EnumPropPages(LPDEVICE_INFO pdi, LPFNADDPROPSHEETPAGE pfnAdd, LPARAM lParam )
+{
+ FIXME("(%p %p %lx)\n",pdi,pfnAdd,lParam);
+ return FALSE;
+}
+
+/*
+ * These data structures are convert from values used in fields of a DCB
+ * to strings used in the CommConfigDialog.
+ */
+typedef struct tagPARAM2STRDATA
+{
+ DWORD val;
+ CONST CHAR *name;
+} PARAM2STRDATA, *LPPARAM2STRDATA;
+
+typedef struct tagPARAM2STR
+{
+ DWORD dwSize;
+ LPPARAM2STRDATA data;
+} PARAM2STR, *LPPARAM2STR;
+typedef const LPPARAM2STR LPCPARAM2STR;
+
+#define SERIALUI_TABLESIZE(x) ((sizeof (x))/(sizeof (x[0])))
+
+static PARAM2STRDATA SERIALUI_Baud2StrData[]={
+ {110, "110"}, {300, "300"}, {600, "600"}, {1200, "1200"},
+ {2400, "2400"}, {4800, "4800"}, {9600, "9600"}, {14400, "14400"},
+ {19200, "19200"}, {38400L, "38400"}, {56000L, "56000"}, {57600L, "57600"},
+ {115200L, "115200"}, {128000L, "128000"}, {256000L, "256000"}
+};
+static PARAM2STR SERIALUI_Baud2Str={ SERIALUI_TABLESIZE(SERIALUI_Baud2StrData),SERIALUI_Baud2StrData };
+
+static PARAM2STRDATA SERIALUI_Parity2StrData[]={
+ {NOPARITY,"None"}, {ODDPARITY,"Odd"}, {EVENPARITY,"Even"}, {MARKPARITY,"Mark"},
+ {SPACEPARITY,"Space"}
+};
+static PARAM2STR SERIALUI_Parity2Str={ SERIALUI_TABLESIZE(SERIALUI_Parity2StrData),SERIALUI_Parity2StrData };
+
+static PARAM2STRDATA SERIALUI_Stop2StrData[]={
+ {ONESTOPBIT,"1"}, {ONE5STOPBITS,"1.5"}, {TWOSTOPBITS,"2"}
+};
+static PARAM2STR SERIALUI_Stop2Str={ SERIALUI_TABLESIZE(SERIALUI_Stop2StrData),SERIALUI_Stop2StrData };
+
+static PARAM2STRDATA SERIALUI_Data2StrData[]={
+ {5,"5"}, {6,"6"}, {7,"7"}, {8, "8"}, {16,"16"}
+};
+static PARAM2STR SERIALUI_Data2Str={ SERIALUI_TABLESIZE(SERIALUI_Data2StrData),SERIALUI_Data2StrData };
+
+static PARAM2STRDATA SERIALUI_Flow2StrData[]={
+ {0,"None"}, {1,"Hardware (RTS/CTS)"}, {2,"Software (XON/XOFF)"}
+};
+static PARAM2STR SERIALUI_Flow2Str={ SERIALUI_TABLESIZE(SERIALUI_Flow2StrData),SERIALUI_Flow2StrData };
+
+/*
+ * Add all the fields to a combo box and highlight the current value
+ */
+static void SERIALUI_AddConfItems(HWND hDlg, DWORD id, LPCPARAM2STR table, DWORD dwVal)
+{
+ int i,n;
+ HWND hControl = GetDlgItem(hDlg,id);
+
+ if(!hControl)
+ return;
+
+ for(i=0; i<table->dwSize; i++)
+ {
+ n = SendMessageA(hControl, CB_ADDSTRING, 0L, (LPARAM)table->data[i].name);
+ if(dwVal == table->data[i].val)
+ {
+ SendMessageA(hControl, CB_SETCURSEL, (WPARAM)n, (LPARAM)0);
+ }
+ }
+}
+
+/*
+ * Get the current sellection of the given combo box and set a DCB field to
+ * the value matching that selection.
+ */
+static BOOL SERIALUI_GetConfItems(HWND hDlg, DWORD id, LPCPARAM2STR table, LPDWORD lpdwVal)
+{
+ DWORD i;
+ CHAR lpEntry[20];
+ HWND hControl = GetDlgItem(hDlg,id);
+
+ if( (!hControl) || (!lpdwVal))
+ {
+ TRACE("Couldn't get window handle for item %lx\n",id);
+ return FALSE;
+ }
+
+ if(!GetWindowTextA(hControl, &lpEntry[0], sizeof lpEntry))
+ {
+ TRACE("Couldn't get window text for item %lx\n",id);
+ return FALSE;
+ }
+ /* TRACE("%ld contains %s\n",id, lpEntry); */
+
+ for(i=0; i<table->dwSize; i++)
+ {
+ if(!lstrcmpA(table->data[i].name,lpEntry))
+ {
+ *lpdwVal = table->data[i].val;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ * Both the enumerated values CBR_XXXX and integer baud rates are valid
+ * dcb.BaudRate. This code is to convert back and forth between CBR_ style
+ * and integers. The dialog box uses integer values.
+ */
+static DWORD SERIALUI_BaudConvertTable[] = {
+ CBR_110, 110, CBR_300, 300, CBR_600, 600, CBR_1200, 1200,
+ CBR_2400, 2400, CBR_4800, 4800, CBR_9600, 9600, CBR_14400, 14400,
+ CBR_19200, 19200, CBR_38400, 38400, CBR_56000, 56000, CBR_57600, 57600,
+ CBR_115200, 115200, CBR_128000, 128000, CBR_256000, 256000
+};
+
+static BOOL SERIALUI_MakeBaudDword(LPDWORD lpdwBaudRate)
+{
+ int i;
+
+ for(i=0; i<(sizeof(SERIALUI_BaudConvertTable)/sizeof(DWORD)); i+=2)
+ {
+ if(*lpdwBaudRate == SERIALUI_BaudConvertTable[i])
+ {
+ *lpdwBaudRate = SERIALUI_BaudConvertTable[i+1];
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static BOOL SERIALUI_MakeBaudEnum(LPDWORD lpdwBaudRate)
+{
+ int i;
+
+ for(i=0; i<(sizeof(SERIALUI_BaudConvertTable)/sizeof(DWORD)); i+=2)
+ {
+ if(*lpdwBaudRate == SERIALUI_BaudConvertTable[i+1])
+ {
+ *lpdwBaudRate = SERIALUI_BaudConvertTable[i];
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+typedef struct tagSERIALUI_DialogInfo
+{
+ LPCSTR lpszDevice;
+ LPCOMMCONFIG lpCommConfig;
+ BOOL bConvert; /* baud rate was converted to a DWORD */
+ DWORD dwFlowControl; /* old flow control */
+} SERIALUI_DialogInfo;
+
+static void SERIALUI_DCBToDialogInfo(HWND hDlg, SERIALUI_DialogInfo *info)
+{
+ DWORD dwBaudRate, dwStopBits, dwParity, dwByteSize, dwFlowControl;
+ LPDCB lpdcb = &info->lpCommConfig->dcb;
+
+ /* pass integer pointers to SERIALUI_ dialog config fns */
+ dwBaudRate = lpdcb->BaudRate;
+ dwStopBits = lpdcb->StopBits;
+ dwParity = lpdcb->Parity;
+ dwByteSize = lpdcb->ByteSize;
+
+ /* map flow control state, if it looks normal */
+ if((lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE) ||
+ (lpdcb->fOutxCtsFlow == TRUE)) {
+ dwFlowControl = 1;
+ } else if(lpdcb->fOutX || lpdcb->fInX) {
+ dwFlowControl = 2;
+ } else {
+ dwFlowControl = 0;
+ }
+
+ info->bConvert = SERIALUI_MakeBaudDword(&dwBaudRate);
+
+ SERIALUI_AddConfItems( hDlg, IDC_BAUD, &SERIALUI_Baud2Str ,dwBaudRate);
+ SERIALUI_AddConfItems( hDlg, IDC_STOP, &SERIALUI_Stop2Str ,dwStopBits);
+ SERIALUI_AddConfItems( hDlg, IDC_PARITY, &SERIALUI_Parity2Str ,dwParity);
+ SERIALUI_AddConfItems( hDlg, IDC_DATA, &SERIALUI_Data2Str ,dwByteSize);
+ SERIALUI_AddConfItems( hDlg, IDC_FLOW, &SERIALUI_Flow2Str, dwFlowControl );
+
+ info->dwFlowControl = dwFlowControl;
+}
+
+static void SERIALUI_DialogInfoToDCB(HWND hDlg, SERIALUI_DialogInfo *info)
+{
+ DWORD dwBaudRate, dwStopBits, dwParity, dwByteSize, dwFlowControl;
+ LPDCB lpdcb = &info->lpCommConfig->dcb;
+
+ SERIALUI_GetConfItems( hDlg, IDC_BAUD, &SERIALUI_Baud2Str, &dwBaudRate);
+ SERIALUI_GetConfItems( hDlg, IDC_STOP, &SERIALUI_Stop2Str, &dwStopBits);
+ SERIALUI_GetConfItems( hDlg, IDC_PARITY, &SERIALUI_Parity2Str, &dwParity);
+ SERIALUI_GetConfItems( hDlg, IDC_DATA, &SERIALUI_Data2Str, &dwByteSize);
+ SERIALUI_GetConfItems( hDlg, IDC_FLOW, &SERIALUI_Flow2Str, &dwFlowControl );
+
+ TRACE("baud=%ld stop=%ld parity=%ld data=%ld flow=%ld\n",
+ dwBaudRate, dwStopBits, dwParity, dwByteSize, dwFlowControl);
+
+ lpdcb->BaudRate = dwBaudRate;
+ lpdcb->StopBits = dwStopBits;
+ lpdcb->Parity = dwParity;
+ lpdcb->ByteSize = dwByteSize;
+
+ /* try not to change flow control if the user didn't change it */
+ if(info->dwFlowControl != dwFlowControl)
+ {
+ switch(dwFlowControl)
+ {
+ case 0:
+ lpdcb->fOutxCtsFlow = FALSE;
+ lpdcb->fOutxDsrFlow = FALSE;
+ lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
+ lpdcb->fOutX = FALSE;
+ lpdcb->fInX = FALSE;
+ lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
+ break;
+ case 1: /* CTS/RTS */
+ lpdcb->fOutxCtsFlow = TRUE;
+ lpdcb->fOutxDsrFlow = FALSE;
+ lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
+ lpdcb->fOutX = FALSE;
+ lpdcb->fInX = FALSE;
+ lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
+ break;
+ case 2:
+ lpdcb->fOutxCtsFlow = FALSE;
+ lpdcb->fOutxDsrFlow = FALSE;
+ lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
+ lpdcb->fOutX = TRUE;
+ lpdcb->fInX = TRUE;
+ lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
+ break;
+ }
+ }
+
+ if(info->bConvert)
+ SERIALUI_MakeBaudEnum(&lpdcb->BaudRate);
+}
+
+/***********************************************************************
+ * SERIALUI_ConfigDialogProc
+ *
+ * Shows a dialog for configuring a COMM port
+ */
+BOOL WINAPI SERIALUI_ConfigDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ CHAR szTitle[30];
+ SERIALUI_DialogInfo *info;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ info = (SERIALUI_DialogInfo*) lParam;
+ if(!info)
+ return FALSE;
+ SetWindowLongA(hWnd, DWL_USER, lParam);
+ wsnprintfA(szTitle, sizeof szTitle, "Settings for %s", info->lpszDevice);
+ SetWindowTextA(hWnd, szTitle);
+ SERIALUI_DCBToDialogInfo(hWnd, info);
+ return TRUE;
+
+ case WM_COMMAND:
+ {
+ WORD wID = LOWORD(wParam);
+
+ info = (SERIALUI_DialogInfo *) GetWindowLongA(hWnd, DWL_USER);
+ if(!info)
+ EndDialog(hWnd,0);
+ switch (wID)
+ {
+ case IDOK:
+ SERIALUI_DialogInfoToDCB(hWnd,info);
+ EndDialog(hWnd,1);
+ return TRUE;
+ case IDCANCEL:
+ EndDialog(hWnd,0);
+ return TRUE;
+/* test code for Get/SetDefaultCommConfig begins */
+ case ID_GETDEFAULT:
+ {
+ DWORD r,dwConfSize = sizeof (COMMCONFIG);
+ r = GetDefaultCommConfigA(info->lpszDevice,
+ info->lpCommConfig, &dwConfSize);
+ if(!r)
+ MessageBoxA(hWnd,"Failed","GetDefaultCommConfig",MB_OK);
+ }
+ SERIALUI_DCBToDialogInfo(hWnd, info);
+ break;
+ case ID_SETDEFAULT:
+ {
+ DWORD r;
+ SERIALUI_DialogInfoToDCB(hWnd,info);
+ r = SetDefaultCommConfigA(info->lpszDevice,
+ info->lpCommConfig, sizeof (COMMCONFIG));
+ if(!r)
+ MessageBoxA(hWnd,"Failed","GetDefaultCommConfig",MB_OK);
+ }
+ break;
+/* test code for Get/SetDefaultCommConfig ends */
+ }
+ }
+ default:
+ return FALSE;
+ }
+}
+
+/***********************************************************************
+ * SERIALUI_CommConfigDialog (SERIALUI.3)
+ *
+ * Used by Win9x KERNEL to show a dialog for configuring a COMM port.
+ */
+BOOL WINAPI SERIALUI_CommConfigDialog(
+ LPCSTR lpszName,
+ HWND hWndParent,
+ LPCOMMCONFIG lpCommConfig
+) {
+ SERIALUI_DialogInfo info;
+
+ info.lpCommConfig = lpCommConfig;
+ info.lpszDevice = lpszName;
+ info.bConvert = FALSE;
+ info.dwFlowControl = 0;
+
+ if(!lpCommConfig)
+ return FALSE;
+
+ return DialogBoxParamA(SERIALUI_hModule,
+ MAKEINTRESOURCEA(IDD_SERIALUICONFIG),
+ hWndParent,
+ (DLGPROC) SERIALUI_ConfigDialogProc,
+ (LPARAM)&info);
+}
+
+static LPCSTR lpszCommKey = "System\\CurrentControlSet\\Services\\Class\\Ports";
+static LPCSTR lpszDCB = "DCB";
+
+/***********************************************************************
+ * SERIALUI_SetDefaultCommConfig (SERIALUI.4)
+ *
+ * Used by Win98 KERNEL to set the default config for a COMM port
+ * FIXME: uses the wrong registry key... should use a digit, not
+ * the comm port name.
+ */
+BOOL WINAPI SERIALUI_SetDefaultCommConfig(
+ LPCSTR lpszDevice,
+ LPCOMMCONFIG lpCommConfig,
+ DWORD dwSize
+) {
+ HKEY hKeyReg=0, hKeyPort=0;
+ CHAR szKeyName[100];
+ DWORD r,dwDCBSize;
+
+ TRACE("%p %p %lx\n",lpszDevice,lpCommConfig,dwSize);
+
+ if(!lpCommConfig)
+ return FALSE;
+
+ if(dwSize < sizeof (COMMCONFIG))
+ return FALSE;
+
+ r = RegConnectRegistryA(NULL, HKEY_LOCAL_MACHINE, &hKeyReg);
+ if(r != ERROR_SUCCESS)
+ return FALSE;
+
+ wsnprintfA(szKeyName, sizeof szKeyName, "%s\\%s", lpszCommKey ,lpszDevice);
+ r = RegCreateKeyA(hKeyReg, szKeyName, &hKeyPort);
+ if(r == ERROR_SUCCESS)
+ {
+ dwDCBSize = sizeof (DCB);
+ r = RegSetValueExA( hKeyPort, lpszDCB, NULL, REG_BINARY,
+ (LPSTR)&lpCommConfig->dcb,dwDCBSize);
+ TRACE("write key r=%ld\n",r);
+ RegCloseKey(hKeyPort);
+ }
+
+ RegCloseKey(hKeyReg);
+
+ return (r==ERROR_SUCCESS);
+}
+
+/***********************************************************************
+ * SERIALUI_GetDefaultCommConfig (SERIALUI.5)
+ *
+ * Used by Win9x KERNEL to get the default config for a COMM port
+ * FIXME: uses the wrong registry key... should use a digit, not
+ * the comm port name.
+ */
+BOOL WINAPI SERIALUI_GetDefaultCommConfig(
+ LPCSTR lpszDevice,
+ LPCOMMCONFIG lpCommConfig,
+ LPDWORD lpdwSize
+) {
+ HKEY hKeyReg, hKeyPort;
+ CHAR szKeyName[100];
+ DWORD r,dwSize,dwType;
+
+ TRACE("%p %p %p\n",lpszDevice,lpCommConfig,lpdwSize);
+
+ if(!lpCommConfig)
+ return FALSE;
+
+ if(!lpdwSize)
+ return FALSE;
+
+ if(*lpdwSize < sizeof (COMMCONFIG))
+ return FALSE;
+
+ *lpdwSize = sizeof (COMMCONFIG);
+ memset(lpCommConfig, 0 , sizeof (COMMCONFIG));
+ lpCommConfig->dwSize = sizeof (COMMCONFIG);
+ lpCommConfig->wVersion = 1;
+
+ r = RegConnectRegistryA(NULL, HKEY_LOCAL_MACHINE, &hKeyReg);
+ if(r != ERROR_SUCCESS)
+ return FALSE;
+
+ wsnprintfA(szKeyName, sizeof szKeyName, "%s\\%s", lpszCommKey ,lpszDevice);
+ r = RegOpenKeyA(hKeyReg, szKeyName, &hKeyPort);
+ if(r == ERROR_SUCCESS)
+ {
+ dwSize = sizeof (DCB);
+ dwType = 0;
+ r = RegQueryValueExA( hKeyPort, lpszDCB, NULL,
+ &dwType, (LPSTR)&lpCommConfig->dcb,&dwSize);
+ if ((r==ERROR_SUCCESS) && (dwType != REG_BINARY))
+ r = 1;
+ if ((r==ERROR_SUCCESS) && (dwSize != sizeof(DCB)))
+ r = 1;
+
+ RegCloseKey(hKeyPort);
+ }
+ else
+ {
+ /* FIXME: default to a hardcoded commconfig */
+
+ lpCommConfig->dcb.DCBlength = sizeof(DCB);
+ lpCommConfig->dcb.BaudRate = 9600;
+ lpCommConfig->dcb.fBinary = TRUE;
+ lpCommConfig->dcb.fParity = FALSE;
+ lpCommConfig->dcb.ByteSize = 8;
+ lpCommConfig->dcb.Parity = NOPARITY;
+ lpCommConfig->dcb.StopBits = ONESTOPBIT;
+ lpCommConfig->dcb.StopBits = ONESTOPBIT;
+ return TRUE;
+ }
+
+ RegCloseKey(hKeyReg);
+
+ return (r==ERROR_SUCCESS);
+}
diff --git a/dlls/serialui/serialui.h b/dlls/serialui/serialui.h
new file mode 100644
index 0000000..71805bc
--- /dev/null
+++ b/dlls/serialui/serialui.h
@@ -0,0 +1,9 @@
+#define IDD_SERIALUICONFIG 0x401
+#define IDC_BAUD 0x402
+#define IDC_PARITY 0x0403
+#define IDC_STOP 0x0404
+#define IDC_FLOW 0x0405
+#define IDC_DATA 0x0406
+
+#define ID_GETDEFAULT 0x410
+#define ID_SETDEFAULT 0x411
diff --git a/dlls/serialui/serialui.spec b/dlls/serialui/serialui.spec
new file mode 100644
index 0000000..bf94dc3
--- /dev/null
+++ b/dlls/serialui/serialui.spec
@@ -0,0 +1,9 @@
+name serialui
+type win32
+init SERIALUI_LibMain
+rsrc serialui_rc
+
+2 stdcall EnumPropPages(ptr ptr ptr) SERIALUI_EnumPropPages
+3 stdcall drvCommConfigDialog(ptr long ptr) SERIALUI_CommConfigDialog
+4 stdcall drvSetDefaultCommConfig() SERIALUI_SetDefaultCommConfig
+5 stdcall drvGetDefaultCommConfig() SERIALUI_GetDefaultCommConfig
diff --git a/dlls/serialui/serialui_rc.rc b/dlls/serialui/serialui_rc.rc
new file mode 100644
index 0000000..f4d8503
--- /dev/null
+++ b/dlls/serialui/serialui_rc.rc
@@ -0,0 +1,26 @@
+#include "windef.h"
+#include "winuser.h"
+#include "serialui.h"
+
+
+IDD_SERIALUICONFIG DIALOG DISCARDABLE 0, 0, 160, 159
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
+CAPTION "Properties for "
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "Baud Rate", 0,5,20,55,10
+ COMBOBOX IDC_BAUD, 60, 20, 90, 36, CBS_DROPDOWNLIST|CBS_AUTOHSCROLL|WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Parity", 0,5,40,55,10
+ COMBOBOX IDC_PARITY, 60, 40, 90, 36, CBS_DROPDOWNLIST|CBS_AUTOHSCROLL|WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Flow Control", 0,5,60,55,10
+ COMBOBOX IDC_FLOW, 60, 60, 90, 36, CBS_DROPDOWNLIST|CBS_AUTOHSCROLL|WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Data Bits", 0,5,80,55,10
+ COMBOBOX IDC_DATA, 60, 80, 90, 36, CBS_DROPDOWNLIST|CBS_AUTOHSCROLL|WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Stop Bits", 0,5,100,55,10
+ COMBOBOX IDC_STOP, 60, 100, 90, 36, CBS_DROPDOWNLIST|CBS_AUTOHSCROLL|WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK", IDOK,30,138,50,14
+ PUSHBUTTON "Cancel", IDCANCEL,85,138,50,14
+ /* these two buttons are for testing Get/SetDefaultCommConfig */
+ /* PUSHBUTTON "GetDefault", ID_GETDEFAULT,30,115,50,14 */
+ /* PUSHBUTTON "SetDefault", ID_SETDEFAULT,85,115,50,14 */
+END