Source code of Windows XP (NT5)
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.

982 lines
24 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Copyright (c) Microsoft Corporation 1993-1996
  4. //
  5. // File: serialui.c
  6. //
  7. // This files contains the DLL entry-points.
  8. //
  9. // Much of this file contains the code that builds the default property dialog
  10. // for serial ports.
  11. //
  12. // History:
  13. // 1-12-94 ScottH Created
  14. // 8-15-94 ScottH Split from modemui.dll
  15. // 11-06-95 ScottH Ported to NT
  16. //
  17. //---------------------------------------------------------------------------
  18. #include "proj.h" // common headers
  19. #define INITGUID
  20. #include <objbase.h>
  21. #include <initguid.h>
  22. #include <devguid.h>
  23. #pragma data_seg(DATASEG_READONLY)
  24. LPGUID c_pguidModem = (LPGUID)&GUID_DEVCLASS_MODEM;
  25. // (scotth): it looks like for the NT SUR release, that there
  26. // will be no Port class key or GUID. So we have to hack something
  27. // up.
  28. #ifdef DCB_IN_REGISTRY
  29. LPGUID c_pguidPort = (LPGUID)&GUID_DEVCLASS_PORT;
  30. #else
  31. LPGUID c_pguidPort = (LPGUID)NULL;
  32. #endif
  33. #pragma data_seg()
  34. #define MAX_PROP_PAGES 8 // Define a reasonable limit
  35. #ifdef DEBUG
  36. //-----------------------------------------------------------------------------------
  37. // Debug routines
  38. //-----------------------------------------------------------------------------------
  39. /*----------------------------------------------------------
  40. Purpose: Dumps the DCB struct
  41. Returns: --
  42. Cond: --
  43. */
  44. void PRIVATE DumpDCB(
  45. LPWIN32DCB pdcb)
  46. {
  47. ASSERT(pdcb);
  48. if (IsFlagSet(g_dwDumpFlags, DF_DCB))
  49. {
  50. int i;
  51. LPDWORD pdw = (LPDWORD)pdcb;
  52. TRACE_MSG(TF_ALWAYS, "DCB %08lx %08lx %08lx %08lx", pdw[0], pdw[1], pdw[2], pdw[3]);
  53. pdw += 4;
  54. for (i = 0; i < sizeof(WIN32DCB)/sizeof(DWORD); i += 4, pdw += 4)
  55. {
  56. TRACE_MSG(TF_ALWAYS, " %08lx %08lx %08lx %08lx", pdw[0], pdw[1], pdw[2], pdw[3]);
  57. }
  58. }
  59. }
  60. #endif //DEBUG
  61. //-----------------------------------------------------------------------------------
  62. //
  63. //-----------------------------------------------------------------------------------
  64. /*----------------------------------------------------------
  65. Purpose: Composes a string of the format "baud,parity,data,stopbit"
  66. Returns: --
  67. Cond: --
  68. */
  69. void PRIVATE ComposeModeComString(
  70. LPCOMMCONFIG pcc,
  71. LPTSTR pszBuffer)
  72. {
  73. WIN32DCB FAR * pdcb = &pcc->dcb;
  74. TCHAR chParity;
  75. LPCTSTR pszStop;
  76. TCHAR chFlow;
  77. const static TCHAR rgchParity[] = {'n', 'o', 'e', 'm', 's'};
  78. const static LPCTSTR rgpszStop[] = {TEXT("1"), TEXT("1.5"), TEXT("2")};
  79. // Parity
  80. // ASSERT(!pdcb->fParity && NOPARITY == pdcb->Parity || pdcb->fParity);
  81. ASSERT(0 <= pdcb->Parity && ARRAYSIZE(rgchParity) > pdcb->Parity);
  82. if (0 <= pdcb->Parity && ARRAYSIZE(rgchParity) > pdcb->Parity)
  83. {
  84. chParity = rgchParity[pdcb->Parity];
  85. }
  86. else
  87. {
  88. chParity = rgchParity[0]; // Safety net
  89. }
  90. // Stop bits
  91. ASSERT(0 <= pdcb->StopBits && ARRAYSIZE(rgpszStop) > pdcb->StopBits);
  92. if (0 <= pdcb->StopBits && ARRAYSIZE(rgpszStop) > pdcb->StopBits)
  93. {
  94. pszStop = rgpszStop[pdcb->StopBits];
  95. }
  96. else
  97. {
  98. pszStop = rgpszStop[0]; // Safety net
  99. }
  100. // Flow control
  101. if (FALSE != pdcb->fOutX && FALSE == pdcb->fOutxCtsFlow)
  102. {
  103. chFlow = 'x'; // XON/XOFF flow control
  104. }
  105. else if (FALSE == pdcb->fOutX && FALSE != pdcb->fOutxCtsFlow)
  106. {
  107. chFlow = 'p'; // Hardware flow control
  108. }
  109. else
  110. {
  111. chFlow = ' '; // No flow control
  112. }
  113. wsprintf(pszBuffer, TEXT("%ld,%c,%d,%s,%c"), pdcb->BaudRate, chParity, pdcb->ByteSize,
  114. pszStop, chFlow);
  115. }
  116. /*----------------------------------------------------------
  117. Purpose: Initialize the port info.
  118. Returns: --
  119. Cond: --
  120. */
  121. void PRIVATE InitializePortInfo(
  122. LPCTSTR pszFriendlyName,
  123. LPPORTINFO pportinfo,
  124. LPCOMMCONFIG pcc)
  125. {
  126. ASSERT(pportinfo);
  127. ASSERT(pcc);
  128. // Read-only fields
  129. pportinfo->pcc = pcc;
  130. CopyMemory(&pportinfo->dcb, &pcc->dcb, sizeof(pportinfo->dcb));
  131. lstrcpyn(pportinfo->szFriendlyName, pszFriendlyName, SIZECHARS(pportinfo->szFriendlyName));
  132. }
  133. /*----------------------------------------------------------
  134. Purpose: Gets a WIN32DCB from the registry.
  135. Returns: One of the ERROR_ values
  136. Cond: --
  137. */
  138. DWORD
  139. PRIVATE
  140. RegQueryDCB(
  141. IN LPFINDDEV pfd,
  142. OUT WIN32DCB FAR * pdcb)
  143. {
  144. DWORD dwRet = ERROR_BADKEY;
  145. #ifdef DCB_IN_REGISTRY
  146. DWORD cbData;
  147. ASSERT(pdcb);
  148. // Does the DCB key exist in the driver key?
  149. if (ERROR_SUCCESS == RegQueryValueEx(pfd->hkeyDrv, c_szDCB, NULL, NULL, NULL, &cbData))
  150. {
  151. // Yes; is the size in the registry okay?
  152. if (sizeof(*pdcb) < cbData)
  153. {
  154. // No; the registry has bogus data
  155. dwRet = ERROR_BADDB;
  156. }
  157. else
  158. {
  159. // Yes; get the DCB from the registry
  160. if (ERROR_SUCCESS == RegQueryValueEx(pfd->hkeyDrv, c_szDCB, NULL, NULL, (LPBYTE)pdcb, &cbData))
  161. {
  162. if (sizeof(*pdcb) == pdcb->DCBlength)
  163. {
  164. dwRet = NO_ERROR;
  165. }
  166. else
  167. {
  168. dwRet = ERROR_BADDB;
  169. }
  170. }
  171. else
  172. {
  173. dwRet = ERROR_BADKEY;
  174. }
  175. }
  176. }
  177. #else
  178. static TCHAR const FAR c_szDefaultDCBString[] = TEXT("9600,n,8,1");
  179. TCHAR sz[MAX_BUF_MED];
  180. TCHAR szKey[MAX_BUF_SHORT];
  181. lstrcpy(szKey, pfd->szPort);
  182. lstrcat(szKey, TEXT(":"));
  183. GetProfileString(c_szPortClass, szKey, c_szDefaultDCBString, sz, SIZECHARS(sz));
  184. TRACE_MSG(TF_GENERAL, "DCB string is \"%s\"", sz);
  185. // Convert the DCB string to a DCB structure
  186. if ( !BuildCommDCB(sz, pdcb) )
  187. {
  188. dwRet = GetLastError();
  189. ASSERT(NO_ERROR != dwRet);
  190. }
  191. else
  192. {
  193. dwRet = NO_ERROR;
  194. }
  195. #endif
  196. return dwRet;
  197. }
  198. /*----------------------------------------------------------
  199. Purpose: Save the DCB to the permanent storage
  200. Returns: win32 error
  201. Cond: --
  202. */
  203. DWORD
  204. PRIVATE
  205. RegSetDCB(
  206. IN LPFINDDEV pfd,
  207. IN WIN32DCB FAR * pdcb)
  208. {
  209. DWORD dwRet;
  210. #ifdef DCB_IN_REGISTRY
  211. DWORD cbData;
  212. // Write the DCB to the driver key
  213. cbData = sizeof(WIN32DCB);
  214. dwRet = RegSetValueEx(pfd->hkeyDrv, c_szDCB, 0, REG_BINARY, (LPBYTE)&pcc->dcb, cbData);
  215. #else
  216. dwRet = NO_ERROR;
  217. #endif
  218. return dwRet;
  219. }
  220. /*----------------------------------------------------------
  221. Purpose: Frees the portinfo struct
  222. Returns: --
  223. Cond: --
  224. */
  225. void PRIVATE FreePortInfo(
  226. LPPORTINFO pportinfo)
  227. {
  228. if (pportinfo)
  229. {
  230. if (pportinfo->pcc)
  231. LocalFree(LOCALOF(pportinfo->pcc));
  232. LocalFree(LOCALOF(pportinfo));
  233. }
  234. }
  235. /*----------------------------------------------------------
  236. Purpose: Release the data associated with the Port Settings page
  237. Returns: --
  238. Cond: --
  239. */
  240. UINT CALLBACK PortSettingsCallback(
  241. HWND hwnd,
  242. UINT uMsg,
  243. LPPROPSHEETPAGE ppsp)
  244. {
  245. DBG_ENTER("PortSettingsCallback");
  246. if (PSPCB_RELEASE == uMsg)
  247. {
  248. LPPORTINFO pportinfo = (LPPORTINFO)ppsp->lParam;
  249. LPCOMMCONFIG pcc;
  250. ASSERT(pportinfo);
  251. pcc = pportinfo->pcc;
  252. if (IDOK == pportinfo->idRet)
  253. {
  254. // Save the changes back to the commconfig struct
  255. TRACE_MSG(TF_GENERAL, "Saving DCB");
  256. CopyMemory(&pcc->dcb, &pportinfo->dcb, sizeof(pcc->dcb));
  257. DEBUG_CODE( DumpDCB(&pcc->dcb); )
  258. // Are we releasing from the Device Mgr?
  259. if (IsFlagSet(pportinfo->uFlags, SIF_FROM_DEVMGR))
  260. {
  261. // Yes; save the commconfig now as well
  262. drvSetDefaultCommConfig(pportinfo->szFriendlyName, pcc, pcc->dwSize);
  263. // Free the portinfo struct only when called from the Device Mgr
  264. FreePortInfo(pportinfo);
  265. }
  266. }
  267. TRACE_MSG(TF_GENERAL, "Releasing the Port Settings page");
  268. }
  269. DBG_EXIT("PortSettingsCallback");
  270. return TRUE;
  271. }
  272. /*----------------------------------------------------------
  273. Purpose: Add the port settings page.
  274. Returns: ERROR_ value
  275. Cond: --
  276. */
  277. DWORD PRIVATE AddPortSettingsPage(
  278. LPPORTINFO pportinfo,
  279. LPFNADDPROPSHEETPAGE pfnAdd,
  280. LPARAM lParam)
  281. {
  282. DWORD dwRet = ERROR_NOT_ENOUGH_MEMORY;
  283. PROPSHEETPAGE psp;
  284. HPROPSHEETPAGE hpage;
  285. ASSERT(pportinfo);
  286. ASSERT(pfnAdd);
  287. // Add the Port Settings property page
  288. //
  289. psp.dwSize = sizeof(PROPSHEETPAGE);
  290. psp.dwFlags = PSP_USECALLBACK;
  291. psp.hInstance = g_hinst;
  292. psp.pszTemplate = MAKEINTRESOURCE(IDD_PORTSETTINGS);
  293. psp.pfnDlgProc = Port_WrapperProc;
  294. psp.lParam = (LPARAM)pportinfo;
  295. psp.pfnCallback = PortSettingsCallback;
  296. hpage = CreatePropertySheetPage(&psp);
  297. if (hpage)
  298. {
  299. if (!pfnAdd(hpage, lParam))
  300. DestroyPropertySheetPage(hpage);
  301. else
  302. dwRet = NO_ERROR;
  303. }
  304. return dwRet;
  305. }
  306. /*----------------------------------------------------------
  307. Purpose: Function that is called by EnumPropPages entry-point to
  308. add property pages.
  309. Returns: TRUE on success
  310. FALSE on failure
  311. Cond: --
  312. */
  313. BOOL CALLBACK AddInstallerPropPage(
  314. HPROPSHEETPAGE hPage,
  315. LPARAM lParam)
  316. {
  317. PROPSHEETHEADER FAR * ppsh = (PROPSHEETHEADER FAR *)lParam;
  318. if (ppsh->nPages < MAX_PROP_PAGES)
  319. {
  320. ppsh->phpage[ppsh->nPages] = hPage;
  321. ++ppsh->nPages;
  322. return(TRUE);
  323. }
  324. return(FALSE);
  325. }
  326. /*----------------------------------------------------------
  327. Purpose: Bring up property sheet for a serial port
  328. Returns: ERROR_ value
  329. Cond: --
  330. */
  331. DWORD PRIVATE DoProperties(
  332. LPCTSTR pszFriendlyName,
  333. HWND hwndParent,
  334. LPCOMMCONFIG pcc)
  335. {
  336. DWORD dwRet;
  337. PROPSHEETHEADER psh;
  338. HPROPSHEETPAGE hpsPages[MAX_PROP_PAGES];
  339. LPPORTINFO pportinfo;
  340. // Initialize the PropertySheet Header
  341. psh.dwSize = sizeof(psh);
  342. psh.dwFlags = PSH_PROPTITLE;
  343. psh.hwndParent = hwndParent;
  344. psh.hInstance = g_hinst;
  345. psh.nPages = 0;
  346. psh.nStartPage = 0;
  347. psh.phpage = (HPROPSHEETPAGE FAR *)hpsPages;
  348. // Allocate the working buffer
  349. //
  350. pportinfo = (LPPORTINFO)LocalAlloc(LPTR, sizeof(*pportinfo));
  351. if (pportinfo)
  352. {
  353. InitializePortInfo(pszFriendlyName, pportinfo, pcc);
  354. psh.pszCaption = pportinfo->szFriendlyName;
  355. DEBUG_CODE( DumpDCB(&pcc->dcb); )
  356. dwRet = AddPortSettingsPage(pportinfo, AddInstallerPropPage, (LPARAM)&psh);
  357. if (NO_ERROR == dwRet)
  358. {
  359. // Show the property sheet
  360. PropertySheet(&psh);
  361. dwRet = (IDOK == pportinfo->idRet) ? NO_ERROR : ERROR_CANCELLED;
  362. }
  363. // Clear the pcc field so FreePortInfo does not prematurely free it,
  364. // since we did not allocate it.
  365. pportinfo->pcc = NULL;
  366. FreePortInfo(pportinfo);
  367. }
  368. else
  369. {
  370. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  371. }
  372. return dwRet;
  373. }
  374. #ifdef WIN95
  375. // The Device Manager allows DLLs to add pages to the properties
  376. // of a device. EnumPropPages is the entry-point that it would
  377. // call to add pages.
  378. //
  379. // This is not implemented in NT.
  380. /*----------------------------------------------------------
  381. Purpose: Derives a PORTINFO struct from a device info.
  382. Returns: TRUE on success
  383. Cond: --
  384. */
  385. BOOL PRIVATE DeviceInfoToPortInfo(
  386. LPDEVICE_INFO pdi,
  387. LPPORTINFO pportinfo)
  388. {
  389. BOOL bRet = FALSE;
  390. LPFINDDEV pfd;
  391. COMMCONFIG ccDummy;
  392. LPCOMMCONFIG pcommconfig;
  393. DWORD cbSize;
  394. DWORD cbData;
  395. TCHAR szFriendly[MAXFRIENDLYNAME];
  396. // Find the device by looking for the device description. (Note the
  397. // device description is not always the same as the friendly name.)
  398. if (FindDev_Create(&pfd, c_pguidPort, c_szDeviceDesc, pdi->szDescription))
  399. {
  400. cbData = sizeof(szFriendly);
  401. if (ERROR_SUCCESS == RegQueryValueEx(pfd->hkeyDev, c_szFriendlyName, NULL, NULL,
  402. (LPBYTE)szFriendly, &cbData))
  403. {
  404. ccDummy.dwProviderSubType = PST_RS232;
  405. cbSize = sizeof(COMMCONFIG);
  406. drvGetDefaultCommConfig(szFriendly, &ccDummy, &cbSize);
  407. pcommconfig = (LPCOMMCONFIG)LocalAlloc(LPTR, (UINT)cbSize);
  408. if (pcommconfig)
  409. {
  410. // Get the commconfig from the registry
  411. pcommconfig->dwProviderSubType = PST_RS232;
  412. if (NO_ERROR == drvGetDefaultCommConfig(szFriendly, pcommconfig,
  413. &cbSize))
  414. {
  415. // Initialize the modem info from the commconfig
  416. InitializePortInfo(szFriendly, pportinfo, pcommconfig);
  417. SetFlag(pportinfo->uFlags, SIF_FROM_DEVMGR);
  418. bRet = TRUE;
  419. }
  420. else
  421. {
  422. // Failure
  423. LocalFree(LOCALOF(pcommconfig));
  424. }
  425. // pcommconfig is freed in ReleasePortSettingsPage
  426. }
  427. }
  428. FindDev_Destroy(pfd);
  429. }
  430. return bRet;
  431. }
  432. /*----------------------------------------------------------
  433. Purpose: EnumDevicePropPages entry-point. This entry-point
  434. gets called only when the Device Manager asks for
  435. additional property pages.
  436. Returns: TRUE on success
  437. FALSE if pages could not be added
  438. Cond: --
  439. */
  440. BOOL WINAPI EnumPropPages(
  441. LPDEVICE_INFO pdi,
  442. LPFNADDPROPSHEETPAGE pfnAdd,
  443. LPARAM lParam) // Don't touch the lParam value, just pass it on!
  444. {
  445. BOOL bRet = FALSE;
  446. LPPORTINFO pportinfo;
  447. DBG_ENTER("EnumPropPages");
  448. ASSERT(pdi);
  449. ASSERT(pfnAdd);
  450. pportinfo = (LPPORTINFO)LocalAlloc(LPTR, sizeof(*pportinfo));
  451. if (pportinfo)
  452. {
  453. // Convert the device info struct to a portinfo.
  454. bRet = DeviceInfoToPortInfo(pdi, pportinfo);
  455. if (bRet)
  456. {
  457. AddPortSettingsPage(pportinfo, pfnAdd, lParam);
  458. }
  459. else
  460. {
  461. // Failed
  462. FreePortInfo(pportinfo);
  463. }
  464. // pportinfo is freed in ReleasePortSettingsPage
  465. }
  466. DBG_EXIT_BOOL("EnumPropPages", bRet);
  467. return bRet;
  468. }
  469. #endif
  470. /*----------------------------------------------------------
  471. Purpose: Invokes the serial port configuration dialog.
  472. Returns: One of the ERROR_ values
  473. Cond: --
  474. */
  475. DWORD
  476. PRIVATE
  477. MyCommConfigDialog(
  478. IN LPFINDDEV pfd,
  479. IN LPCTSTR pszFriendlyName,
  480. IN HWND hwndOwner,
  481. IN OUT LPCOMMCONFIG pcc)
  482. {
  483. DWORD dwRet;
  484. ASSERT(pfd);
  485. // (Wrapper should have checked these first)
  486. ASSERT(pszFriendlyName);
  487. ASSERT(pcc);
  488. ASSERT(sizeof(*pcc) <= pcc->dwSize);
  489. dwRet = DoProperties(pszFriendlyName, hwndOwner, pcc);
  490. return dwRet;
  491. }
  492. /*----------------------------------------------------------
  493. Purpose: Gets the default COMMCONFIG for the specified device.
  494. This API doesn't require a handle.
  495. If the caller passed in a null device name or a null
  496. commconfig pointer, this function will set *pdwSize to
  497. the minimum COMMCONFIG size. Calling this function
  498. a second time (after setting the dwSize and dwProviderSubType
  499. fields) will verify if the size is correct.
  500. So generally, when getting a commconfig for serial ports,
  501. the process is:
  502. COMMCONFIG ccDummy;
  503. LPCOMMCONFIG pcc;
  504. DWORD dwSize = sizeof(*pcc);
  505. // Determine real size of COMMCONFIG for RS-232 subtype
  506. ccDummy.dwProviderSubType = PST_RS232;
  507. GetDefaultCommConfig(pszFriendlyName, &ccDummy, &dwSize);
  508. // Allocate real commconfig struct and initialize
  509. pcc = LocalAlloc(LPTR, dwSize);
  510. if (pcc)
  511. {
  512. pcc->dwProviderSubType = PST_RS232;
  513. GetDefaultCommConfig(pszFriendlyName, pcc, &dwSize);
  514. ....
  515. }
  516. Returns: One of the ERROR_ values in winerror.h
  517. Cond: --
  518. */
  519. DWORD
  520. PRIVATE
  521. MyGetDefaultCommConfig(
  522. IN LPFINDDEV pfd,
  523. IN LPCTSTR pszFriendlyName,
  524. OUT LPCOMMCONFIG pcc,
  525. OUT LPDWORD pdwSize)
  526. {
  527. DWORD dwRet;
  528. ASSERT(pfd);
  529. // (Wrapper should have checked these first)
  530. ASSERT(pszFriendlyName);
  531. ASSERT(pcc);
  532. ASSERT(pdwSize);
  533. ASSERT(sizeof(*pcc) <= *pdwSize);
  534. *pdwSize = sizeof(*pcc);
  535. // Initialize the commconfig structure
  536. pcc->dwSize = *pdwSize;
  537. pcc->wVersion = COMMCONFIG_VERSION_1;
  538. pcc->dwProviderSubType = PST_RS232;
  539. pcc->dwProviderOffset = 0;
  540. pcc->dwProviderSize = 0;
  541. dwRet = RegQueryDCB(pfd, &pcc->dcb);
  542. DEBUG_CODE( DumpDCB(&pcc->dcb); )
  543. return dwRet;
  544. }
  545. /*----------------------------------------------------------
  546. Purpose: Sets the default COMMCONFIG for the specified device.
  547. This API doesn't require a handle. This function
  548. strictly modifies the registry. Use SetCommConfig
  549. to set the COMMCONFIG of an open device.
  550. If the dwSize parameter or the dwSize field are invalid
  551. sizes (given the dwProviderSubType field in COMMCONFIG),
  552. then this function fails.
  553. Returns: One of the ERROR_ return values
  554. Cond: --
  555. */
  556. DWORD
  557. PRIVATE
  558. MySetDefaultCommConfig(
  559. IN LPFINDDEV pfd,
  560. IN LPCTSTR pszFriendlyName,
  561. IN LPCOMMCONFIG pcc)
  562. {
  563. DWORD dwRet;
  564. TCHAR szValue[MAX_BUF_SHORT];
  565. TCHAR szKey[MAX_BUF_SHORT];
  566. ASSERT(pfd);
  567. // (Wrapper should have checked these first)
  568. ASSERT(pszFriendlyName);
  569. ASSERT(pcc);
  570. ASSERT(sizeof(*pcc) <= pcc->dwSize);
  571. ASSERT(0 == pcc->dwProviderSize);
  572. ASSERT(0 == pcc->dwProviderOffset);
  573. dwRet = RegSetDCB(pfd, &pcc->dcb);
  574. if (NO_ERROR == dwRet)
  575. {
  576. // For Win 3.1 compatibility, write some info to win.ini
  577. lstrcpy(szKey, pfd->szPort);
  578. lstrcat(szKey, TEXT(":"));
  579. // Delete the old win.ini entry first
  580. WriteProfileString(c_szPortClass, szKey, NULL);
  581. ComposeModeComString(pcc, szValue);
  582. WriteProfileString(c_szPortClass, szKey, szValue);
  583. #ifdef WIN95
  584. {
  585. DWORD dwRecipients;
  586. // Send a broadcast proclaiming that the win.ini has changed
  587. // (Use the internal BroadcastSystemMessage to avoid deadlocks.
  588. // SendMessageTimeout would be more appropriate, but that is
  589. // not exported for 16-bit dlls. PostMessage is not good because
  590. // lParam is a pointer.)
  591. dwRecipients = BSM_APPLICATIONS;
  592. BroadcastSystemMessage(BSF_NOHANG, &dwRecipients, WM_WININICHANGE,
  593. NULL, (LPARAM)c_szPortClass);
  594. }
  595. #else
  596. {
  597. SendNotifyMessage(HWND_BROADCAST, WM_WININICHANGE, 0, (LPARAM)c_szPortClass);
  598. }
  599. #endif
  600. }
  601. DEBUG_CODE( DumpDCB(&pcc->dcb); )
  602. return dwRet;
  603. }
  604. //-----------------------------------------------------------------------------------
  605. // Entry-points provided for KERNEL32 APIs
  606. //-----------------------------------------------------------------------------------
  607. DWORD
  608. APIENTRY
  609. #ifdef UNICODE
  610. drvCommConfigDialogA(
  611. IN LPCSTR pszFriendlyName,
  612. IN HWND hwndOwner,
  613. IN OUT LPCOMMCONFIG pcc)
  614. #else
  615. drvCommConfigDialogW(
  616. IN LPCWSTR pszFriendlyName,
  617. IN HWND hwndOwner,
  618. IN OUT LPCOMMCONFIG pcc)
  619. #endif
  620. {
  621. return ERROR_CALL_NOT_IMPLEMENTED;
  622. }
  623. /*----------------------------------------------------------
  624. Purpose: Entry point for CommConfigDialog
  625. Returns: standard error value in winerror.h
  626. Cond: --
  627. */
  628. DWORD
  629. APIENTRY
  630. drvCommConfigDialog(
  631. IN LPCTSTR pszFriendlyName,
  632. IN HWND hwndOwner,
  633. IN OUT LPCOMMCONFIG pcc)
  634. {
  635. DWORD dwRet;
  636. LPFINDDEV pfd;
  637. DEBUG_CODE( TRACE_MSG(TF_FUNC, "drvCommConfigDialog(%s, ...) entered",
  638. Dbg_SafeStr(pszFriendlyName)); )
  639. // We support friendly names (eg, "Communications Port (COM1)") or
  640. // portname values (eg, "COM1").
  641. if (NULL == pszFriendlyName ||
  642. NULL == pcc)
  643. {
  644. dwRet = ERROR_INVALID_PARAMETER;
  645. }
  646. // Is the size sufficient?
  647. else if (sizeof(*pcc) > pcc->dwSize)
  648. {
  649. // No
  650. dwRet = ERROR_INSUFFICIENT_BUFFER;
  651. }
  652. else if (FindDev_Create(&pfd, c_pguidPort, c_szFriendlyName, pszFriendlyName) ||
  653. FindDev_Create(&pfd, c_pguidPort, c_szPortName, pszFriendlyName) ||
  654. FindDev_Create(&pfd, c_pguidModem, c_szPortName, pszFriendlyName))
  655. {
  656. dwRet = MyCommConfigDialog(pfd, pszFriendlyName, hwndOwner, pcc);
  657. FindDev_Destroy(pfd);
  658. }
  659. else
  660. {
  661. dwRet = ERROR_BADKEY;
  662. }
  663. DBG_EXIT_DWORD("drvCommConfigDialog", dwRet);
  664. return dwRet;
  665. }
  666. DWORD
  667. APIENTRY
  668. #ifdef UNICODE
  669. drvGetDefaultCommConfigA(
  670. IN LPCSTR pszFriendlyName,
  671. IN LPCOMMCONFIG pcc,
  672. IN OUT LPDWORD pdwSize)
  673. #else
  674. drvGetDefaultCommConfigW(
  675. IN LPCWSTR pszFriendlyName,
  676. IN LPCOMMCONFIG pcc,
  677. IN OUT LPDWORD pdwSize)
  678. #endif
  679. {
  680. return ERROR_CALL_NOT_IMPLEMENTED;
  681. }
  682. /*----------------------------------------------------------
  683. Purpose: Entry point for GetDefaultCommConfig
  684. Returns: standard error value in winerror.h
  685. Cond: --
  686. */
  687. DWORD
  688. APIENTRY
  689. drvGetDefaultCommConfig(
  690. IN LPCTSTR pszFriendlyName,
  691. IN LPCOMMCONFIG pcc,
  692. IN OUT LPDWORD pdwSize)
  693. {
  694. DWORD dwRet;
  695. LPFINDDEV pfd;
  696. DEBUG_CODE( TRACE_MSG(TF_FUNC, "drvGetDefaultCommConfig(%s, ...) entered",
  697. Dbg_SafeStr(pszFriendlyName)); )
  698. // We support friendly names (eg, "Communications Port (COM1)") or
  699. // portname values (eg, "COM1").
  700. if (NULL == pszFriendlyName ||
  701. NULL == pcc ||
  702. NULL == pdwSize)
  703. {
  704. dwRet = ERROR_INVALID_PARAMETER;
  705. }
  706. // Is the size sufficient?
  707. else if (sizeof(*pcc) > *pdwSize)
  708. {
  709. // No; return correct value
  710. dwRet = ERROR_INSUFFICIENT_BUFFER;
  711. *pdwSize = sizeof(*pcc);
  712. }
  713. else if (FindDev_Create(&pfd, c_pguidPort, c_szFriendlyName, pszFriendlyName) ||
  714. FindDev_Create(&pfd, c_pguidPort, c_szPortName, pszFriendlyName) ||
  715. FindDev_Create(&pfd, c_pguidModem, c_szPortName, pszFriendlyName))
  716. {
  717. dwRet = MyGetDefaultCommConfig(pfd, pszFriendlyName, pcc, pdwSize);
  718. FindDev_Destroy(pfd);
  719. }
  720. else
  721. {
  722. dwRet = ERROR_BADKEY;
  723. }
  724. DBG_EXIT_DWORD("drvGetDefaultCommConfig", dwRet);
  725. return dwRet;
  726. }
  727. DWORD
  728. APIENTRY
  729. #ifdef UNICODE
  730. drvSetDefaultCommConfigA(
  731. IN LPSTR pszFriendlyName,
  732. IN LPCOMMCONFIG pcc,
  733. IN DWORD dwSize)
  734. #else
  735. drvSetDefaultCommConfigW(
  736. IN LPWSTR pszFriendlyName,
  737. IN LPCOMMCONFIG pcc,
  738. IN DWORD dwSize)
  739. #endif
  740. {
  741. return ERROR_CALL_NOT_IMPLEMENTED;
  742. }
  743. /*----------------------------------------------------------
  744. Purpose: Entry point for SetDefaultCommConfig
  745. Returns: standard error value in winerror.h
  746. Cond: --
  747. */
  748. DWORD
  749. APIENTRY
  750. drvSetDefaultCommConfig(
  751. IN LPTSTR pszFriendlyName,
  752. IN LPCOMMCONFIG pcc,
  753. IN DWORD dwSize)
  754. {
  755. DWORD dwRet;
  756. LPFINDDEV pfd;
  757. DEBUG_CODE( TRACE_MSG(TF_FUNC, "drvSetDefaultCommConfig(%s, ...) entered",
  758. Dbg_SafeStr(pszFriendlyName)); )
  759. // We support friendly names (eg, "Communications Port (COM1)") or
  760. // portname values (eg, "COM1").
  761. if (NULL == pszFriendlyName ||
  762. NULL == pcc)
  763. {
  764. dwRet = ERROR_INVALID_PARAMETER;
  765. }
  766. // Is the size sufficient?
  767. else if ((sizeof(*pcc) > pcc->dwSize) || (sizeof(*pcc) > dwSize))
  768. {
  769. // No
  770. dwRet = ERROR_INSUFFICIENT_BUFFER;
  771. }
  772. else if (FindDev_Create(&pfd, c_pguidPort, c_szFriendlyName, pszFriendlyName) ||
  773. FindDev_Create(&pfd, c_pguidPort, c_szPortName, pszFriendlyName) ||
  774. FindDev_Create(&pfd, c_pguidModem, c_szPortName, pszFriendlyName))
  775. {
  776. dwRet = MySetDefaultCommConfig(pfd, pszFriendlyName, pcc);
  777. FindDev_Destroy(pfd);
  778. }
  779. else
  780. {
  781. dwRet = ERROR_BADKEY;
  782. }
  783. DBG_EXIT_DWORD("drvSetDefaultCommConfig", dwRet);
  784. return dwRet;
  785. }