Leaked source code of windows server 2003
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.

645 lines
16 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1998
  4. *
  5. * TITLE: Main.Cpp
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: ReedB
  10. *
  11. * DATE: 9 Jan, 1998
  12. *
  13. * DESCRIPTION:
  14. *
  15. * Implementation of WinMain for WIA device manager server device object.
  16. *
  17. *******************************************************************************/
  18. #include "precomp.h"
  19. #include "stiexe.h"
  20. #include "wiamindr.h"
  21. #include "wiacfact.h"
  22. #include "devmgr.h"
  23. #include "wialog.h"
  24. #include "wiaevntp.h"
  25. //
  26. // Image transfer critical section.
  27. //
  28. CRITICAL_SECTION g_semDeviceMan;
  29. //
  30. // Critical section for event node, should only be used in event notifier
  31. //
  32. CRITICAL_SECTION g_semEventNode;
  33. //
  34. // data to initialize WiaDevMgr CLSID
  35. //
  36. FACTORY_DATA g_FactoryData[] =
  37. {
  38. {CWiaDevMgr::CreateInstance, // Object creator
  39. NULL, // Pointer to running class factory
  40. 0, // ID for running object
  41. &CLSID_WiaDevMgr, // Class ID
  42. &LIBID_WiaDevMgr, // Type Library ID
  43. TEXT("WIA Device Manager"), // Friendly Name
  44. TEXT("WiaDevMgr.1"), // Program ID
  45. TEXT("WiaDevMgr"), // Version-independent Program ID
  46. TEXT("StiSvc"), // Service ID
  47. SERVICE_FILE_NAME} // Filename
  48. };
  49. UINT g_uiFactoryDataCount = sizeof(g_FactoryData) / sizeof(FACTORY_DATA);
  50. //
  51. // data to initialize WiaLog CLSID
  52. //
  53. FACTORY_DATA g_LogFactoryData[] =
  54. {
  55. {CWiaLog::CreateInstance, // Object creator
  56. NULL, // Pointer to running class factory
  57. 0, // ID for running object
  58. &CLSID_WiaLog, // Class ID
  59. &LIBID_WiaDevMgr, // Type Library ID (Logging shares Type lib)
  60. TEXT("WIA Logger"), // Friendly Name
  61. TEXT("WiaLog.1"), // Program ID
  62. TEXT("WiaLog"), // Version-independent Program ID
  63. TEXT("StiSvc"), // Service ID (Logging uses same service)
  64. SERVICE_FILE_NAME} // Filename (Logging uses same .exe)
  65. };
  66. UINT g_uiLogFactoryDataCount = sizeof(g_LogFactoryData) / sizeof(FACTORY_DATA);
  67. //
  68. // Private function proto's:
  69. //
  70. LRESULT CALLBACK WiaMainWndProc(HWND, UINT, UINT, LONG);
  71. /**************************************************************************\
  72. * ProcessWiaMsg
  73. *
  74. * !!! minimal message server: is this needed
  75. *
  76. * Arguments:
  77. *
  78. * hwnd - window handle
  79. * uMsg - message
  80. * wParam - param
  81. * lParam - param
  82. *
  83. * Return Value:
  84. *
  85. * Status
  86. *
  87. * History:
  88. *
  89. * 4/8/1999 Original Version
  90. *
  91. \**************************************************************************/
  92. HRESULT ProcessWiaMsg(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  93. {
  94. switch (uMsg) {
  95. case WM_CREATE:
  96. break;
  97. case WM_DESTROY:
  98. if (CFactory::CanUnloadNow() != S_OK) {
  99. //
  100. // Don't let STI process this message.
  101. //
  102. return S_OK;
  103. }
  104. break;
  105. case WM_CLOSE:
  106. break;
  107. }
  108. //
  109. // Let STI handle the message.
  110. //
  111. return S_FALSE;
  112. }
  113. #if 0
  114. /**************************************************************************\
  115. * DispatchWiaMsg
  116. *
  117. * Handle Event messages
  118. *
  119. *
  120. * !!! WM_NOTIFY_WIA_VOLUME_EVENT is a temp hack and needs to be
  121. * added for real or removed
  122. *
  123. * Arguments:
  124. *
  125. * pMsg WM_NOTIFY_WIA_DEV_EVENT or WM_NOTIFY_WIA_VOLUME_EVENT
  126. *
  127. * Return Value:
  128. *
  129. * Status
  130. *
  131. * History:
  132. *
  133. * 4/8/1999 Original Version
  134. *
  135. \**************************************************************************/
  136. HRESULT DispatchWiaMsg(MSG *pMsg)
  137. {
  138. DBG_FN(::DispatchWiaMsg);
  139. PWIANOTIFY pwn;
  140. if (pMsg->message == WM_NOTIFY_WIA_DEV_EVENT) {
  141. //
  142. // find out if this is a valid WIA event, call handler
  143. //
  144. DBG_ERR(("WIA Processing WM_NOTIFY_WIA_DEV_EVENT: shouldn't be called"));
  145. //
  146. // event are now directly fired, not posted
  147. //
  148. #if 0
  149. pwn = (PWIANOTIFY) pMsg->lParam;
  150. if (pwn && (pwn->lSize == sizeof(WIANOTIFY))) {
  151. if (g_eventNotifier.NotifySTIEvent(pwn) == S_FALSE) {
  152. DBG_WRN(("::DispatchWiaMsg, No Applications were registered for this event"));
  153. }
  154. SysFreeString(pwn->bstrDevId);
  155. LocalFree(pwn);
  156. }
  157. else {
  158. DBG_ERR(("::DispatchWiaMsg, Bad WIA notify data"));
  159. }
  160. #endif
  161. } else if (pMsg->message == WM_NOTIFY_WIA_VOLUME_EVENT) {
  162. //
  163. // WIA volume arrival
  164. //
  165. DBG_TRC(("::DispatchWiaMsg, WIA Processing WM_NOTIFY_WIA_VOLUME_EVENT"));
  166. PWIANOTIFY_VOLUME pwn = (PWIANOTIFY_VOLUME) pMsg->lParam;
  167. if (pwn && (pwn->lSize == sizeof(WIANOTIFY_VOLUME))) {
  168. //
  169. // look at root fo volume for WIA File wia.cmd
  170. //
  171. int i;
  172. char c = 'A';
  173. DWORD mask = pwn->unitmask;
  174. //
  175. // find drive letter
  176. //
  177. if (mask & 0x07ffffff) {
  178. for (i=0;i<24;i++) {
  179. if (mask & 0x00000001) {
  180. break;
  181. }
  182. c++;
  183. mask >>= 1;
  184. }
  185. //
  186. // build file name
  187. //
  188. char FileName[MAX_PATH];
  189. FileName[0] = c;
  190. FileName[1] = ':';
  191. FileName[2] = '\\';
  192. FileName[3] = 'w';
  193. FileName[4] = 'i';
  194. FileName[5] = 'a';
  195. FileName[6] = '.';
  196. FileName[7] = 'c';
  197. FileName[8] = 'm';
  198. FileName[9] = 'd';
  199. FileName[10] = '\0';
  200. //
  201. // open file
  202. //
  203. HANDLE hFile = CreateFileA(
  204. FileName,
  205. GENERIC_WRITE | GENERIC_READ ,
  206. FILE_SHARE_WRITE,
  207. NULL,
  208. OPEN_EXISTING,
  209. FILE_ATTRIBUTE_NORMAL,
  210. NULL
  211. );
  212. if (hFile != INVALID_HANDLE_VALUE) {
  213. //
  214. // file name is on volume root
  215. //
  216. if (g_eventNotifier.NotifyVolumeEvent(pwn) == S_FALSE) {
  217. DBG_WRN(("::DispatchWiaMsg, No Applications were registered for this Volume event"));
  218. }
  219. CloseHandle(hFile);
  220. }
  221. }
  222. //
  223. // free message
  224. //
  225. LocalFree(pwn);
  226. }
  227. else {
  228. DBG_ERR(("::DispatchWiaMsg, Bad WIA notify data"));
  229. }
  230. }
  231. //
  232. // Let STI handle the message.
  233. //
  234. return S_FALSE;
  235. }
  236. #endif
  237. /**************************************************************************\
  238. * RegisterWiaDevMan
  239. *
  240. * Register WiaDevMgr class factory
  241. *
  242. * Arguments:
  243. *
  244. * bRegister - register/unregister
  245. *
  246. * Return Value:
  247. *
  248. * Status
  249. *
  250. * History:
  251. *
  252. * 4/8/1999 Original Version
  253. *
  254. \**************************************************************************/
  255. HRESULT RegisterWiaDevMan(BOOLEAN bRegister)
  256. {
  257. HRESULT hr = CFactory::RegisterUnregisterAll(g_FactoryData,
  258. g_uiFactoryDataCount,
  259. bRegister,
  260. TRUE);
  261. if(SUCCEEDED(hr)) {
  262. hr = CFactory::RegisterUnregisterAll(g_LogFactoryData,
  263. g_uiLogFactoryDataCount,
  264. bRegister,
  265. TRUE);
  266. }
  267. return hr;
  268. }
  269. /**************************************************************************\
  270. * StartLOGClassFactories
  271. *
  272. * Starts the Class factories for WIA logging object
  273. *
  274. * Arguments:
  275. *
  276. * none
  277. *
  278. * Return Value:
  279. *
  280. * Status
  281. *
  282. * History:
  283. *
  284. * 8/23/1999 Original Version
  285. *
  286. \**************************************************************************/
  287. HRESULT StartLOGClassFactories()
  288. {
  289. #ifdef WINNT
  290. HRESULT hr = S_OK;
  291. //
  292. // Set COM security options.
  293. // NOTE: Calling CoInitializeSecurity will override any DCOM
  294. // AccessPermissions that have been set (these are stored under
  295. // our AppID key). We really want to use these permissions and
  296. // not a hardcoded security descriptor, so that if a vendor wanted
  297. // to enable shared/remote scanning, all they need to do is adjust
  298. // the DCOM AccessPermissions on the Wia Device Manager object.
  299. // This can be done either through DCOM Config GUI, or programatically
  300. // via the vendor's installation program. (See our ClassFactory for
  301. // an example of how to set the AccessPermissions. When we are installed,
  302. // we set default access permissions when doing our COM registration).
  303. // The way we get COM to use the DCOM AccessPermissions for the WIA
  304. // Device Manager, is we pass in the AppID (as a pointer to a GUID); and
  305. // the EOAC_APPID flag indicating that the first parameter is an AppID
  306. // rather than a security descriptor. This informs COM that the
  307. // security descriptor should be taken from this objects AppID entry
  308. // in the registry.
  309. //
  310. hr = CoInitializeSecurity((PVOID)&CLSID_WiaDevMgr,
  311. -1,
  312. NULL,
  313. NULL,
  314. RPC_C_AUTHN_LEVEL_CONNECT,
  315. RPC_C_IMP_LEVEL_IMPERSONATE,
  316. NULL,
  317. EOAC_DYNAMIC_CLOAKING | EOAC_APPID,
  318. NULL);
  319. if (FAILED(hr)) {
  320. DBG_ERR(("StartLOGClassFactories() CoInitializeSecurity failed, hr = 0x%08X", hr));
  321. ::CoUninitialize();
  322. }
  323. #endif
  324. if (CFactory::StartFactories(g_LogFactoryData, g_uiLogFactoryDataCount))
  325. return S_OK;
  326. else
  327. return E_FAIL;
  328. }
  329. /**************************************************************************\
  330. * InitWiaDevMan
  331. *
  332. * Wia Initialization called from STI
  333. *
  334. * Arguments:
  335. *
  336. * action - Action to be taken
  337. *
  338. * Return Value:
  339. *
  340. * Status
  341. *
  342. * History:
  343. *
  344. * 4/8/1999 Original Version
  345. *
  346. \**************************************************************************/
  347. HRESULT InitWiaDevMan(
  348. WIA_SERVICE_INIT_ACTION action)
  349. {
  350. DBG_FN("InitWiaDevMan");
  351. HRESULT hr = E_FAIL;
  352. switch (action) {
  353. case WiaInitialize:
  354. //
  355. // Get Thread ID and process handle for the class factory.
  356. //
  357. CFactory::s_dwThreadID = GetCurrentThreadId();
  358. CFactory::s_hModule = g_hInst;
  359. /*
  360. //
  361. // This was moved to StartLOGClassFactories(), because of COM security's need
  362. // to be initialized before an object can be CoCreated correctly.
  363. // (investigate better way to do this..)
  364. //
  365. #ifdef WINNT
  366. //
  367. // Set COM security options. For now we set no security.
  368. // We will need to investigate this before shipping.
  369. //
  370. hr = CoInitializeSecurity(NULL,
  371. -1,
  372. NULL,
  373. NULL,
  374. RPC_C_AUTHN_LEVEL_CONNECT,
  375. RPC_C_IMP_LEVEL_IMPERSONATE,
  376. NULL,
  377. 0,
  378. NULL);
  379. if (FAILED(hr)) {
  380. DBG_ERR(("CoInitializeSecurity failed (0x%X)", hr));
  381. ::CoUninitialize();
  382. break;
  383. }
  384. #endif
  385. */
  386. //
  387. // Register all of the class factories.
  388. //
  389. if (CFactory::StartFactories(g_FactoryData, g_uiFactoryDataCount)) {
  390. //
  391. // Restore persistent Event Callbacks
  392. //
  393. hr = g_eventNotifier.RestoreAllPersistentCBs();
  394. }
  395. hr = E_FAIL;
  396. break;
  397. case WiaUninitialize:
  398. //
  399. // Unregister the class factories.
  400. //
  401. CFactory::StopFactories(g_FactoryData, g_uiFactoryDataCount);
  402. CFactory::StopFactories(g_LogFactoryData, g_uiLogFactoryDataCount);
  403. hr = S_OK;
  404. break;
  405. case WiaRegister:
  406. hr = RegisterWiaDevMan(TRUE);
  407. break;
  408. case WiaUnregister:
  409. hr = RegisterWiaDevMan(FALSE);
  410. break;
  411. }
  412. return hr;
  413. }
  414. /**************************************************************************\
  415. * NotifyWiaDeviceEvent
  416. *
  417. * Called by STI service when WIA needs an async notification.
  418. *
  419. * Arguments:
  420. *
  421. * pwszDevID - ID of device generating event
  422. * pEventGUID - event GUID
  423. * dwThreadId - thread event msg needs to be posted to
  424. *
  425. * Return Value:
  426. *
  427. * Status
  428. *
  429. * History:
  430. *
  431. * 4/8/1999 Original Version
  432. *
  433. \**************************************************************************/
  434. HRESULT NotifyWiaDeviceEvent(
  435. LPWSTR pwszDevID,
  436. const GUID *pEventGUID,
  437. PBYTE pNotificationData,
  438. ULONG ulEventType,
  439. DWORD dwThreadId)
  440. {
  441. DBG_FN(NotifyWiaDeviceEvent);
  442. HRESULT hr;
  443. BSTR bstrDevId;
  444. WIANOTIFY wn;
  445. DBG_TRC(("NotifyWiaDeviceEvent, pwszDevID= %S", pwszDevID));
  446. bstrDevId = SysAllocString(pwszDevID);
  447. if (bstrDevId != NULL) {
  448. wn.lSize = sizeof(WIANOTIFY);
  449. wn.bstrDevId = bstrDevId;
  450. wn.stiNotify.dwSize = sizeof(STINOTIFY);
  451. wn.stiNotify.guidNotificationCode = *pEventGUID;
  452. if (! pNotificationData) {
  453. ZeroMemory(&wn.stiNotify.abNotificationData, MAX_NOTIFICATION_DATA);
  454. } else {
  455. CopyMemory(
  456. &wn.stiNotify.abNotificationData,
  457. pNotificationData,
  458. MAX_NOTIFICATION_DATA);
  459. }
  460. g_eventNotifier.NotifySTIEvent(&wn, ulEventType, NULL);
  461. //
  462. // We should return S_TRUE for events that we want STI to
  463. // handle also.
  464. //
  465. SysFreeString(bstrDevId);
  466. hr = S_FALSE;
  467. } else {
  468. hr = E_OUTOFMEMORY;
  469. }
  470. return hr;
  471. }
  472. /**************************************************************************\
  473. * NotifyWiaVolumeEvent
  474. *
  475. * Called by STI service when a removable volume arrives
  476. *
  477. * Arguments:
  478. *
  479. * dbcv_unitmask - volume information flags
  480. * dwThreadId - msg thread
  481. *
  482. * Return Value:
  483. *
  484. * Status
  485. *
  486. * History:
  487. *
  488. * 4/8/1999 Original Version
  489. *
  490. \**************************************************************************/
  491. HRESULT WINAPI NotifyWiaVolumeEvent(
  492. DWORD dbcv_unitmask,
  493. DWORD dwThreadId)
  494. {
  495. PWIANOTIFY_VOLUME pwn;
  496. //
  497. // Validate the thread ID.
  498. //
  499. if (!dwThreadId) {
  500. return E_FAIL;
  501. }
  502. //
  503. // Allocate and fill in WIANOTIFY structure for msg post.
  504. //
  505. pwn = (PWIANOTIFY_VOLUME)LocalAlloc(LPTR, sizeof(WIANOTIFY_VOLUME));
  506. if (pwn) {
  507. pwn->lSize = sizeof(WIANOTIFY_VOLUME);
  508. pwn->unitmask = dbcv_unitmask;
  509. PostThreadMessage(dwThreadId,
  510. WM_NOTIFY_WIA_VOLUME_EVENT,
  511. 0,
  512. (LPARAM)pwn);
  513. } else {
  514. return E_OUTOFMEMORY;
  515. }
  516. //
  517. // We should return S_TRUE for events that we want STI to
  518. // handle also.
  519. //
  520. return S_FALSE;
  521. }