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.

712 lines
13 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. STIMON.CPP
  5. Abstract:
  6. This module contains code for process, running STI/WIA services
  7. Service process is specific for Windows9x OS and represents a wrapper necessary
  8. to create execution environment. On NT svchost.exe or similar will be used to host
  9. service.
  10. Author:
  11. Vlad Sadovsky (vlads) 03-20-99
  12. Environment:
  13. User Mode - Win32
  14. Revision History:
  15. 03-20-99 VladS created
  16. --*/
  17. //
  18. // Include Headers
  19. //
  20. #include "stdafx.h"
  21. #include "resource.h"
  22. #include "initguid.h"
  23. #include <atlapp.h>
  24. #include <atltmp.h>
  25. #include <regstr.h>
  26. #include "stimon.h"
  27. #include "memory.h"
  28. #include "util.h"
  29. //
  30. // STL includes
  31. //
  32. #include <algorithm>
  33. #include <vector>
  34. #include <list>
  35. #include <eventlog.h>
  36. //
  37. // Service list manager
  38. //
  39. #include "svclist.h"
  40. #include <winsvc.h>
  41. //
  42. // Local variables and types definitions
  43. //
  44. using namespace std;
  45. #ifdef USE_MULTIPLE_SERVICES
  46. list<SERVICE_ENTRY> ServiceList;
  47. CComAutoCriticalSection csServiceList;
  48. #endif
  49. HANDLE ServerStartedEvent = NULL;
  50. CMainWindow * pMainWindow = NULL;
  51. SERVICE_ENTRY * pImageServices = NULL;
  52. //
  53. // Local prototypes
  54. //
  55. DWORD
  56. InitGlobalConfigFromReg(
  57. VOID
  58. );
  59. BOOL
  60. DoGlobalInit(
  61. VOID
  62. );
  63. BOOL
  64. DoGlobalTermination(
  65. VOID
  66. );
  67. BOOL
  68. UpdateRunningServer(
  69. VOID
  70. );
  71. HWND
  72. CreateMasterWindow(
  73. VOID
  74. );
  75. BOOL
  76. StartMasterLoop(
  77. PVOID pv
  78. );
  79. BOOL
  80. StartOperation(
  81. VOID
  82. );
  83. BOOL
  84. ParseCommandLine(
  85. LPSTR lpszCmdLine,
  86. UINT *pargc,
  87. PTSTR *argv
  88. );
  89. BOOL
  90. LoadImageService(
  91. PTSTR pszServiceName,
  92. UINT argc,
  93. LPTSTR *argv
  94. );
  95. LONG
  96. OpenServiceParametersKey (
  97. LPCTSTR pszServiceName,
  98. HKEY* phkey
  99. );
  100. LONG
  101. WINAPI
  102. StimonUnhandledExceptionFilter(
  103. struct _EXCEPTION_POINTERS *ExceptionInfo
  104. );
  105. DWORD
  106. WINAPI
  107. StiServiceInstall(
  108. LPTSTR lpszUserName,
  109. LPTSTR lpszUserPassword
  110. );
  111. DWORD
  112. WINAPI
  113. StiServiceRemove(
  114. VOID
  115. );
  116. //
  117. // Missing definitions from Win9x version of windows.h
  118. //
  119. #define RSP_UNREGISTER_SERVICE 0x00000000
  120. #define RSP_SIMPLE_SERVICE 0x00000001
  121. typedef DWORD WINAPI REGISTERSERVICEPROCESS(
  122. DWORD dwProcessId,
  123. DWORD dwServiceType);
  124. //#include "atlexe_i.c"
  125. LONG CExeModule::Unlock()
  126. {
  127. LONG l = CComModule::Unlock();
  128. return l;
  129. }
  130. CExeModule _Module;
  131. BEGIN_OBJECT_MAP(ObjectMap)
  132. END_OBJECT_MAP()
  133. extern "C"
  134. int
  135. WINAPI
  136. #ifdef UNICODE
  137. _tWinMain
  138. #else
  139. WinMain
  140. #endif
  141. (
  142. HINSTANCE hInstance,
  143. HINSTANCE hPrevInstance,
  144. LPTSTR lpCmdLine,
  145. int nShowCmd
  146. )
  147. /*++
  148. Routine Description:
  149. WinMain
  150. Arguments:
  151. Return Value:
  152. Side effects:
  153. --*/
  154. {
  155. UINT argc;
  156. PTSTR argv[10];
  157. DWORD err;
  158. HRESULT hres;
  159. TCHAR szCommandLine[255];
  160. UINT i = 0;
  161. REGISTERSERVICEPROCESS *pfnRegServiceProcess = NULL;
  162. DBGTRACE __s(TEXT("StiMON::WinMain"));
  163. HRESULT hRes = CoInitializeEx(0,COINIT_MULTITHREADED);
  164. // ASSERT SUCCEEDED(hRes)
  165. //
  166. // To use built-in ATL conversion macros
  167. //
  168. USES_CONVERSION;
  169. _Module.Init(ObjectMap, hInstance);
  170. CMessageLoop cMasterLoop;
  171. lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT
  172. ::lstrcpyn(szCommandLine,lpCmdLine,(sizeof(szCommandLine) / sizeof(szCommandLine[0])) - 1);
  173. szCommandLine[sizeof(szCommandLine)/sizeof(szCommandLine[0]) - 1] = TEXT('\0');
  174. //
  175. // Disable hard-error popups and set unhnadled exception filter
  176. //
  177. ::SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX );
  178. ::SetUnhandledExceptionFilter(&StimonUnhandledExceptionFilter);
  179. //
  180. // Initialize globals. If this routine fails, we have to exit immideately
  181. //
  182. if(NOERROR != InitGlobalConfigFromReg()) {
  183. goto ExitMain;
  184. }
  185. //
  186. // Parse command line , set up needed options
  187. //
  188. ParseCommandLine(szCommandLine,&argc,&argv[0]);
  189. DPRINTF(DM_TRACE,TEXT("STIMON: starting with the commnd line : %s "), lpCmdLine);
  190. //
  191. // Other instances of STIMON running ?
  192. //
  193. ServerStartedEvent = ::CreateSemaphore( NULL,
  194. 0,
  195. 1,
  196. STIStartedEvent_name);
  197. err = ::GetLastError();
  198. if ((hPrevInstance) || (err == ERROR_ALREADY_EXISTS)) {
  199. if (UpdateRunningServer()) {
  200. goto ExitAlreadyRunning;
  201. }
  202. //
  203. // Win9x specific: If first instance exists - signal it should stop
  204. //
  205. if ( g_fStoppingRequest ) {
  206. ReleaseSemaphore(ServerStartedEvent,1,NULL);
  207. }
  208. }
  209. DPRINTF(DM_TRACE ,TEXT("STIMON proceeding to create service instance"));
  210. //
  211. // Do global initialization, independent of specific service
  212. //
  213. if (!DoGlobalInit()) {
  214. goto ExitMain;
  215. }
  216. //
  217. // If command line is special - process it and bail out
  218. //
  219. if (g_fRemovingRequest) {
  220. StiServiceRemove();
  221. goto ExitMain;
  222. }
  223. else if (g_fInstallingRequest) {
  224. StiServiceInstall(NULL,NULL);
  225. goto ExitMain;
  226. }
  227. //
  228. // Tell system we are running as service to prevent shutting down on relogon
  229. //
  230. #ifndef WINNT
  231. if (g_fRunningAsService) {
  232. pfnRegServiceProcess = (REGISTERSERVICEPROCESS *)GetProcAddress(
  233. GetModuleHandleA("kernel32.dll"),
  234. "RegisterServiceProcess");
  235. if (pfnRegServiceProcess) {
  236. pfnRegServiceProcess(::GetCurrentProcessId(), RSP_SIMPLE_SERVICE);
  237. } else {
  238. //
  239. // Print out the warning and let the server continue
  240. //
  241. DPRINTF(DM_ERROR, TEXT("RegisterServiceProcess() is not exported by kernel32.dll"));
  242. }
  243. }
  244. #endif
  245. //
  246. // Load and prepare service DLL for execution
  247. //
  248. if ( !LoadImageService(STI_SERVICE_NAME,argc,argv) ) {
  249. DPRINTF(DM_ERROR, TEXT("Unable load imaging service DLL Error=%d"),::GetLastError() );
  250. goto ExitMain;
  251. }
  252. #if USE_HIDDEN_WINDOW
  253. //
  254. // Create hidden window to receive system-wide notifications
  255. //
  256. pMainWindow = new CMainWindow;
  257. pMainWindow->Create();
  258. cMasterLoop.Run();
  259. #else
  260. //
  261. // Wait till somebody wakes us up
  262. //
  263. // WaitForSingleObject(ServerStartedEvent,INFINITE);
  264. #endif
  265. ExitMain:
  266. //
  267. // Global cleanup
  268. //
  269. DPRINTF(DM_TRACE, TEXT("STIMON coming to global cleanup") );
  270. //
  271. // Deregister with kernel (Win9x specific)
  272. //
  273. #ifndef WINNT
  274. if (g_fRunningAsService) {
  275. if (pfnRegServiceProcess) {
  276. pfnRegServiceProcess(::GetCurrentProcessId(), RSP_UNREGISTER_SERVICE);
  277. }
  278. }
  279. #endif
  280. DoGlobalTermination();
  281. ExitAlreadyRunning:
  282. CoUninitialize();
  283. return 0;
  284. }
  285. BOOL
  286. DoGlobalInit(
  287. VOID
  288. )
  289. /*++
  290. Routine Description:
  291. Arguments:
  292. Return Value:
  293. None.
  294. --*/
  295. {
  296. #ifdef MAXDEBUG
  297. StiSetDebugMask(0xffff);
  298. StiSetDebugParameters(TEXT("STIMON"),TEXT(""));
  299. #endif
  300. //
  301. // Do misc. cleanup, which we need to do on startup .
  302. //
  303. // 1. Some shipping packages for Win98 register STIMON entry to Run section, which
  304. // after upgrade creates problem with racing two copies of STIMON. Remove it.
  305. // 2. Register WIA service if there is STIMON left over in Run section
  306. //
  307. HKEY hkRun = NULL;
  308. LONG lRet ;
  309. ULONG lcbValue = 0;
  310. BOOL fNeedToRegister = FALSE;
  311. TCHAR szSvcPath[MAX_PATH] = {TEXT('0')};
  312. if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_RUN, &hkRun) == NO_ERROR) {
  313. DPRINTF(DM_TRACE,TEXT("Removing erroneous entry on cleanup: HKLM\\..\\Run\\%s"),REGSTR_VAL_MONITOR);
  314. lcbValue = sizeof(szSvcPath);
  315. lRet = RegQueryValueEx(hkRun,REGSTR_VAL_MONITOR,NULL,NULL,(LPBYTE)szSvcPath,&lcbValue);
  316. fNeedToRegister = (lRet == NOERROR);
  317. lRet = RegDeleteValue (hkRun, REGSTR_VAL_MONITOR);
  318. RegCloseKey(hkRun);
  319. }
  320. if (fNeedToRegister ) {
  321. LONG lLen;
  322. LONG lNameIndex = 0;
  323. lLen = ::GetModuleFileName(NULL, szSvcPath, sizeof(szSvcPath)/sizeof(szSvcPath[0]));
  324. DPRINTF(DM_TRACE,TEXT("Adding STIMON to RunServices entry on cleanup path is : %s"),szSvcPath);
  325. if ( lLen) {
  326. if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_RUNSERVICES , &hkRun) == NO_ERROR) {
  327. DPRINTF(DM_TRACE,TEXT("Adding STIMON to RunServices entry on cleanup: HKLM\\..\\RunServices\\%s"),REGSTR_VAL_MONITOR);
  328. lcbValue = (::lstrlen(szSvcPath) + 1 ) * sizeof(szSvcPath[0]);
  329. lRet = RegSetValueEx(hkRun,REGSTR_VAL_MONITOR,NULL,REG_SZ,(LPBYTE)szSvcPath,(DWORD)lcbValue);
  330. RegCloseKey(hkRun);
  331. }
  332. }
  333. else {
  334. DPRINTF(DM_ERROR ,TEXT("Failed to get my own path registering Still Image service monitor. LastError=%d "), ::GetLastError());
  335. }
  336. }
  337. return TRUE;
  338. }
  339. BOOL
  340. DoGlobalTermination(
  341. VOID
  342. )
  343. /*++
  344. Routine Description:
  345. Arguments:
  346. Return Value:
  347. None.
  348. --*/
  349. {
  350. if (ServerStartedEvent) {
  351. ::CloseHandle(ServerStartedEvent);
  352. }
  353. //
  354. // Shut down message loop
  355. //
  356. PostQuitMessage(0);
  357. return TRUE;
  358. }
  359. BOOL
  360. UpdateRunningServer(
  361. VOID
  362. )
  363. /*++
  364. Routine Description:
  365. Arguments:
  366. None.
  367. Return Value:
  368. None.
  369. --*/
  370. {
  371. HWND hExistingWindow;
  372. hExistingWindow = ::FindWindow(g_szClass,NULL);
  373. if (!hExistingWindow) {
  374. DPRINTF(DM_TRACE ,TEXT("STIMON second instance did not find first one "));
  375. return FALSE;
  376. }
  377. //
  378. // Server already running , find it 's window and send a message
  379. // with new values of parameters
  380. //
  381. //
  382. // If instructed to stop - do that
  383. //
  384. if ( g_fStoppingRequest ) {
  385. //
  386. // This is Win9x specific
  387. //
  388. DPRINTF(DM_TRACE ,TEXT("STIMON is trying to close first service instance with handle %X"),hExistingWindow);
  389. ::PostMessage(hExistingWindow,WM_CLOSE,0,0L);
  390. }
  391. else {
  392. // Refresh requested ?
  393. if (g_fRefreshDeviceList) {
  394. // Refresh device list
  395. ::PostMessage(hExistingWindow,STIMON_MSG_REFRESH,1,0L);
  396. }
  397. if (STIMON_AD_DEFAULT_POLL_INTERVAL != g_uiDefaultPollTimeout) {
  398. ::SendMessage(hExistingWindow,STIMON_MSG_SET_PARAMETERS,STIMON_MSG_SET_TIMEOUT,g_uiDefaultPollTimeout);
  399. }
  400. }
  401. return TRUE;
  402. }
  403. BOOL
  404. LoadImageService(
  405. PTSTR pszServiceName,
  406. UINT argc,
  407. LPTSTR *argv
  408. )
  409. /*++
  410. Routine Description:
  411. Attempts to load and initialize the imaging services DLL.
  412. Calls initialization related services.
  413. Arguments:
  414. Action - Specifies the initialization action.
  415. Return Value:
  416. TRUE on success, FALSE on failure.
  417. --*/
  418. {
  419. HKEY hkeyService;
  420. HKEY hkeyParams;
  421. LONG lr = 0;
  422. pImageServices = new SERVICE_ENTRY(pszServiceName);
  423. if (pImageServices) {
  424. LPSERVICE_MAIN_FUNCTION pfnMain;
  425. pfnMain = pImageServices->GetServiceMainFunction();
  426. //
  427. // Call main entry point
  428. //
  429. if (pfnMain) {
  430. pfnMain(argc,argv);
  431. }
  432. return TRUE;
  433. }
  434. return FALSE;
  435. }
  436. LONG
  437. WINAPI
  438. StimonUnhandledExceptionFilter(
  439. struct _EXCEPTION_POINTERS *ExceptionInfo
  440. )
  441. /*++
  442. Routine Description:
  443. Filter for catching unhnalded exceptions
  444. Arguments:
  445. Standard
  446. Return Value:
  447. NOERROR
  448. Side effects:
  449. None
  450. --*/
  451. {
  452. PCTSTR pszCommandLine;
  453. PVOID Addr;
  454. pszCommandLine = GetCommandLine ();
  455. if (!pszCommandLine || !*pszCommandLine) {
  456. pszCommandLine = TEXT("<error getting command line>");
  457. }
  458. #if DBG
  459. DebugBreak();
  460. #endif
  461. return 0;
  462. }
  463. DWORD
  464. WINAPI
  465. StiServiceInstall(
  466. LPTSTR lpszUserName,
  467. LPTSTR lpszUserPassword
  468. )
  469. /*++
  470. Routine Description:
  471. Service installation function.
  472. Calls SCM to install STI service, which is running in user security context
  473. BUGBUG Review
  474. Arguments:
  475. Return Value:
  476. None.
  477. --*/
  478. {
  479. DWORD dwError = NOERROR;
  480. return dwError;
  481. } //StiServiceInstall
  482. DWORD
  483. WINAPI
  484. StiServiceRemove(
  485. VOID
  486. )
  487. /*++
  488. Routine Description:
  489. Service removal function. This function calls SCM to remove the STI service.
  490. Arguments:
  491. None.
  492. Return Value:
  493. Return code. Return zero for success
  494. --*/
  495. {
  496. DWORD dwError = NOERROR;
  497. return dwError;
  498. } // StiServiceRemove