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.

388 lines
9.7 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: irprops.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // irprops.cpp : Defines the initialization routines for the DLL.
  11. //
  12. #include "precomp.hxx"
  13. #include "irprops.h"
  14. #include "irpropsheet.h"
  15. #include "debug.h"
  16. BOOL InitInstance();
  17. INT ExitInstance();
  18. BOOL IsFirstInstance();
  19. INT_PTR WINAPI DoPropertiesA(HWND hwnd, LPCSTR CmdLine);
  20. INT_PTR WINAPI DoPropertiesW(HWND hwnd, LPCWSTR CmdLine);
  21. HINSTANCE gHInst;
  22. //
  23. // This records the current active property sheet window handle created
  24. // by this instance. It is set/reset by CIrPropSheet object.
  25. //
  26. HWND g_hwndPropSheet = NULL;
  27. HANDLE g_hMutex = NULL;
  28. BOOL g_bFirstInstance = TRUE;
  29. //
  30. // This records our registered message for inter-instances communications
  31. // The message is registered in CIrpropsApp::InitInstance.
  32. //
  33. UINT g_uIPMsg;
  34. #ifdef _DEBUG
  35. #define new DEBUG_NEW
  36. #undef THIS_FILE
  37. static char THIS_FILE[] = __FILE__;
  38. #endif
  39. extern "C" {
  40. BOOL APIENTRY
  41. DllMain(HANDLE hDll,
  42. DWORD dwReason,
  43. LPVOID lpReserved)
  44. {
  45. IRINFO((_T("DllMain reason %x"), dwReason));
  46. switch (dwReason) {
  47. case DLL_PROCESS_ATTACH:
  48. gHInst = (HINSTANCE) hDll;
  49. return InitInstance();
  50. break;
  51. case DLL_PROCESS_DETACH:
  52. return ExitInstance();
  53. break;
  54. case DLL_THREAD_DETACH:
  55. break;
  56. case DLL_THREAD_ATTACH:
  57. break;
  58. default:
  59. break;
  60. }
  61. return TRUE;
  62. }
  63. }
  64. ////////////////////////////////////////////////////////////////////////
  65. //some globals
  66. APPLETS IRApplet[NUM_APPLETS] = {
  67. {IDI_IRPROPS, IDS_APPLETNAME, IDS_APPLETDESC}
  68. };
  69. /////////////////////////////////////////////////////////////////////////
  70. // CPlApplet function for the control panel
  71. //
  72. LONG CALLBACK CPlApplet(
  73. HWND hwndCPL,
  74. UINT uMsg,
  75. LPARAM lParam1,
  76. LPARAM lParam2)
  77. {
  78. int i;
  79. LPCPLINFO lpCPlInfo;
  80. i = (int) lParam1;
  81. IRINFO((_T("CplApplet message %x"), uMsg));
  82. switch (uMsg)
  83. {
  84. case CPL_INIT: // first message, sent once
  85. if (!IrPropSheet::IsIrDASupported()) {
  86. HPSXA hpsxa;
  87. //
  88. // Check for any installed extensions.
  89. //
  90. hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, sc_szRegWireless, 8);
  91. if (hpsxa) {
  92. //
  93. // We have extensions installed so we have to show the CPL,
  94. // whether IRDA exists or not.
  95. //
  96. SHDestroyPropSheetExtArray(hpsxa);
  97. return TRUE;
  98. }
  99. return FALSE;
  100. }
  101. return TRUE;
  102. case CPL_GETCOUNT: // second message, sent once
  103. return NUM_APPLETS;
  104. break;
  105. case CPL_INQUIRE: // third message, sent once per application
  106. lpCPlInfo = (LPCPLINFO) lParam2;
  107. lpCPlInfo->lData = 0;
  108. lpCPlInfo->idIcon = IRApplet[i].icon;
  109. lpCPlInfo->idName = IRApplet[i].namestring;
  110. lpCPlInfo->idInfo = IRApplet[i].descstring;
  111. break;
  112. case CPL_STARTWPARMSA:
  113. if (-1 == DoPropertiesA(hwndCPL, (LPCSTR)lParam2))
  114. MsgBoxWinError(hwndCPL);
  115. // return true so that we won't get CPL_DBLCLK.
  116. return 1;
  117. break;
  118. case CPL_STARTWPARMSW:
  119. if (-1 == DoPropertiesW(hwndCPL, (LPCWSTR)lParam2))
  120. MsgBoxWinError(hwndCPL);
  121. // return true so that we won't get CPL_DBLCLK.
  122. return 1;
  123. break;
  124. case CPL_DBLCLK: // application icon double-clicked
  125. if (-1 == DoPropertiesA(hwndCPL, (LPCSTR)lParam2))
  126. MsgBoxWinError(hwndCPL);
  127. return 1;
  128. break;
  129. case CPL_STOP: // sent once per application before CPL_EXIT
  130. break;
  131. case CPL_EXIT: // sent once before FreeLibrary is called
  132. break;
  133. default:
  134. break;
  135. }
  136. return 0;
  137. }
  138. //
  139. // This function presents the Wireless link property sheet.
  140. // INPUT:
  141. // hwndParent -- window handle to be used as parent window of
  142. // the property sheet
  143. // lpCmdLine -- optional command line
  144. // 'n" (n in decimal) is start page number(zero-based).
  145. // OUTPUT:
  146. // Return value of PropertySheet API
  147. INT_PTR
  148. DoPropertiesW(
  149. HWND hwndParent,
  150. LPCWSTR lpCmdLine
  151. )
  152. {
  153. INT_PTR Result;
  154. INT StartPage;
  155. IRINFO((_T("DoPropertiesW")));
  156. //
  157. // Assuming no start page was specified.
  158. //
  159. StartPage = -1;
  160. //
  161. // Command line specifies start page number
  162. //
  163. if (lpCmdLine)
  164. {
  165. // skip white chars
  166. while (_T('\0') != *lpCmdLine &&
  167. (_T(' ') == *lpCmdLine || _T('\t') == *lpCmdLine))
  168. {
  169. lpCmdLine++;
  170. }
  171. if (_T('0') <= *lpCmdLine && _T('9') >= *lpCmdLine)
  172. {
  173. StartPage = 0;
  174. do
  175. {
  176. StartPage = StartPage * 10 + *lpCmdLine - _T('0');
  177. lpCmdLine++;
  178. } while (_T('0') <= *lpCmdLine && _T('9') >= *lpCmdLine);
  179. }
  180. }
  181. if (!IsFirstInstance() || NULL != g_hwndPropSheet)
  182. {
  183. IRINFO((_T("Not the first instance")));
  184. HWND hwndPropSheet = HWND_DESKTOP;
  185. if (NULL == g_hwndPropSheet)
  186. {
  187. IRINFO((_T("No window created")));
  188. //
  189. // We are not the first instance. Look for the property sheet
  190. // window created by the first instance.
  191. //
  192. EnumWindows(EnumWinProc, (LPARAM)&hwndPropSheet);
  193. }
  194. else
  195. {
  196. IRINFO((_T("Window active")));
  197. //
  198. // This is not the first call and we have a
  199. // property sheet active(same process, multiple calls)
  200. //
  201. hwndPropSheet = g_hwndPropSheet;
  202. }
  203. if (HWND_DESKTOP != hwndPropSheet)
  204. {
  205. IRINFO((_T("Found the active property sheet.")));
  206. //
  207. // We found the active property sheet
  208. //
  209. // Select the new active page if necessary
  210. //
  211. if (-1 != StartPage)
  212. PropSheet_SetCurSel(hwndPropSheet, NULL, StartPage);
  213. //
  214. // bring the property sheet to the foreground.
  215. //
  216. ::SetForegroundWindow(hwndPropSheet);
  217. }
  218. Result = IDCANCEL;
  219. }
  220. else
  221. {
  222. IRINFO((_T("First instance, creating propertysheet")));
  223. IrPropSheet PropSheet(gHInst, IDS_APPLETNAME, hwndParent, StartPage);
  224. }
  225. return Result;
  226. }
  227. //
  228. // This is our callback function for EnumWindows API.
  229. // It probes for each window handle to see if it is the property sheet
  230. // window created by the previous instance. If it is, it returns
  231. // the window handle in the provided buffer, lParam)
  232. // Input:
  233. // hWnd -- the window handle
  234. // lParam -- (HWND *)
  235. // Output:
  236. // TRUE -- Let Windows continue to call us
  237. // FALSE -- Stop Windows from calling us again
  238. //
  239. BOOL
  240. CALLBACK
  241. EnumWinProc(
  242. HWND hWnd,
  243. LPARAM lParam
  244. )
  245. {
  246. //
  247. // Verify with this window to see if it is the one we are looking for.
  248. //
  249. LRESULT lr;
  250. lr = ::SendMessage(hWnd, g_uIPMsg, (WPARAM)IPMSG_SIGNATURECHECK,
  251. (LPARAM)IPMSG_REQUESTSIGNATURE);
  252. if (IPMSG_REPLYSIGNATURE == lr)
  253. {
  254. if (lParam)
  255. {
  256. // this is the one
  257. *((HWND *)(lParam)) = hWnd;
  258. }
  259. //
  260. // We are done with enumeration.
  261. //
  262. return FALSE;
  263. }
  264. return TRUE;
  265. }
  266. INT_PTR
  267. DoPropertiesA(
  268. HWND hwndParent,
  269. LPCSTR lpCmdLine
  270. )
  271. {
  272. WCHAR CmdLineW[MAX_PATH];
  273. UINT Size;
  274. if (!lpCmdLine)
  275. return DoPropertiesW(hwndParent, NULL);
  276. MultiByteToWideChar(CP_ACP, 0, lpCmdLine, -1, CmdLineW, sizeof(CmdLineW) / sizeof(WCHAR));
  277. return DoPropertiesW(hwndParent, CmdLineW);
  278. }
  279. // This function creates and displays a message box for the given
  280. // win32 error(or last error)
  281. // INPUT:
  282. // hwndParent -- the parent window for the will-be-created message box
  283. // Type -- message styles(MB_xxxx)
  284. // Error -- Error code. If the value is 0
  285. // GetLastError() will be called to retreive the
  286. // real error code.
  287. // CaptionId -- optional string id for caption
  288. // OUTPUT:
  289. // the value return from MessageBox
  290. //
  291. int
  292. MsgBoxWinError(
  293. HWND hwndParent,
  294. DWORD Options,
  295. DWORD Error,
  296. int CaptionId
  297. )
  298. {
  299. if (ERROR_SUCCESS == Error)
  300. Error = GetLastError();
  301. // nonsense to report success!
  302. if (ERROR_SUCCESS == Error)
  303. return IDOK;
  304. TCHAR szMsg[MAX_PATH];
  305. TCHAR szCaption[MAX_PATH];
  306. if (!CaptionId)
  307. CaptionId = IDS_APPLETNAME;
  308. ::LoadString(gHInst, CaptionId, szCaption, sizeof(szCaption) / sizeof(TCHAR));
  309. FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
  310. NULL, Error, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
  311. szMsg, sizeof(szMsg) / sizeof(TCHAR), NULL);
  312. return MessageBox(hwndParent, szMsg, szCaption, Options);
  313. }
  314. BOOL InitInstance()
  315. {
  316. //
  317. // Try to create a named mutex. This give us a clue
  318. // if we are the first instance. We will not close
  319. // the mutex until exit.
  320. //
  321. g_hMutex = CreateMutex(NULL, TRUE, SINGLE_INST_MUTEX);
  322. if (g_hMutex)
  323. {
  324. g_bFirstInstance = ERROR_ALREADY_EXISTS != GetLastError();
  325. //
  326. // register a message for inter-instances communication
  327. //
  328. g_uIPMsg = RegisterWindowMessage(WIRELESSLINK_INTERPROCESSMSG);
  329. SHFusionInitializeFromModuleID(gHInst, 124);
  330. return TRUE;
  331. }
  332. return FALSE;
  333. }
  334. BOOL ExitInstance()
  335. {
  336. if (g_hMutex)
  337. {
  338. CloseHandle(g_hMutex);
  339. g_hMutex = NULL;
  340. }
  341. SHFusionUninitialize();
  342. return TRUE;
  343. }
  344. BOOL IsFirstInstance()
  345. {
  346. return g_bFirstInstance;
  347. }