#include SERVICE_STATUS ServiceStatus; SERVICE_STATUS_HANDLE ServiceHandle; HDEVNOTIFY ServiceNotify; BOOL Ext2ReportStatus( DWORD State, DWORD Exitcode, DWORD Timeout ) { // If we're in the start state then we don't want the control manager // sending us control messages because they'll confuse us. ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; if (State == SERVICE_RUNNING) { ServiceStatus.dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_SESSIONCHANGE ; } // Save the new status we've been given ServiceStatus.dwCurrentState = State; ServiceStatus.dwWin32ExitCode = Exitcode; ServiceStatus.dwWaitHint = Timeout; // Update the checkpoint variable to let the SCM know that we // haven't died if requests take a long time if ((State == SERVICE_RUNNING) || (State == SERVICE_STOPPED)) { ServiceStatus.dwCheckPoint = 0; } else { ServiceStatus.dwCheckPoint++; } // Tell the SCM our new status return SetServiceStatus(ServiceHandle, &ServiceStatus); } void Ext2StopService() { Ext2ReportStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); if (ServiceNotify) { UnregisterDeviceNotification(ServiceNotify); ServiceNotify = NULL; } /* issue stop event to main thread */ Ext2StopPipeSrv(); Ext2ReportStatus(SERVICE_STOPPED, NO_ERROR, 0); } VOID Ext2DrivesChangeNotify(BOOLEAN bArrival) { return; } VOID Ext2CleanupSession(DWORD sid) { } DWORD WINAPI Ext2CtrlService( DWORD ctrlcode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ) { switch(ctrlcode) { case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: // STOP : The service must stop Ext2StopService(); break; case SERVICE_CONTROL_INTERROGATE: // QUERY : Service control manager just wants to know our state break; case SERVICE_CONTROL_DEVICEEVENT: { PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpEventData; PDEV_BROADCAST_DEVICEINTERFACE lpdbi = (PDEV_BROADCAST_DEVICEINTERFACE) lpEventData; if (lpdbv->dbcv_devicetype != DBT_DEVTYP_VOLUME && lpdbi->dbcc_devicetype != DBT_DEVTYP_DEVICEINTERFACE ) { break; } if (dwEventType == DBT_DEVICEREMOVECOMPLETE) { Ext2DrivesChangeNotify(FALSE); } else if (dwEventType == DBT_DEVICEARRIVAL) { Ext2DrivesChangeNotify(TRUE); } break; } case SERVICE_CONTROL_POWEREVENT: switch (dwEventType) { case PBT_APMQUERYSUSPEND: MsgLog("Power event: PBT_APMQUERYSUSPEND.\n"); //Ext2StartFlushThread(); // Ext2FlushVolume(ASSDDISK_VOLUME); break; case PBT_APMQUERYSUSPENDFAILED: MsgLog("Power event: APMQUERYSUSPENDFAILED.\n"); break; case PBT_APMSUSPEND: MsgLog("Power event: PBT_APMSUSPEND.\n"); break; case PBT_APMRESUMESUSPEND: MsgLog("Power event: PBT_APMRESUMESUSPEND.\n"); Ext2DrivesChangeNotify(TRUE); break; case PBT_APMQUERYSTANDBY: MsgLog("Power event: PBT_APMQUERYSTANDBY.\n"); break; case PBT_APMQUERYSTANDBYFAILED: MsgLog("Power event: APMQUERYSTANDBYFAILED.\n"); break; case PBT_APMSTANDBY: MsgLog("Power event: PBT_APMSTANDBY.\n"); break; case PBT_APMRESUMESTANDBY: MsgLog("Power event: PBT_APMRESUMESTANDBY.\n"); break; case PBT_APMRESUMECRITICAL: MsgLog("Power event: PBT_APMRESUMECRITICAL.\n"); break; case PBT_APMPOWERSTATUSCHANGE: MsgLog("Power event: PBT_APMPOWERSTATUSCHANGE\n"); break; case PBT_APMRESUMEAUTOMATIC: MsgLog("Power event: PBT_APMRESUMEAUTOMATIC\n"); break; default: MsgLog("Power event: unknown value %u\n", dwEventType); break; } break; case SERVICE_CONTROL_SESSIONCHANGE: switch (dwEventType) { case WTS_CONSOLE_CONNECT: MsgLog("Session event: Console connected.\n"); break; case WTS_CONSOLE_DISCONNECT: MsgLog("Session event: Console disconnect.\n"); break; case WTS_REMOTE_CONNECT: MsgLog("Session event: Remote connected.\n"); break; case WTS_REMOTE_DISCONNECT: MsgLog("Session event: Remote disconnect.\n"); break; case WTS_SESSION_LOCK: MsgLog("Session event: Session locked.\n"); break; case WTS_SESSION_UNLOCK: MsgLog("Session event: Session unlocked.\n"); break; case WTS_SESSION_LOGON: { PWTSSESSION_NOTIFICATION pwn = (PWTSSESSION_NOTIFICATION)lpEventData; MsgLog("Session event: Session logon.\n"); Ext2StartUserTask(NULL, _T("/startmgr"), pwn->dwSessionId, FALSE); break; } case WTS_SESSION_LOGOFF: { PWTSSESSION_NOTIFICATION pwn = (PWTSSESSION_NOTIFICATION)lpEventData; MsgLog("Session event: Session logoff.\n"); if (pwn && pwn->cbSize >= sizeof(WTSSESSION_NOTIFICATION)) { Ext2CleanupSession(pwn->dwSessionId); } break; } default: MsgLog("Session event: unknown value: %u.\n", dwEventType); break; } break; case SERVICE_ACCEPT_HARDWAREPROFILECHANGE: default: // Control code not recognised break; } // Tell the control manager what we're up to. Ext2ReportStatus(ServiceStatus.dwCurrentState, NO_ERROR, 0); return NO_ERROR; } VOID Ext2StartMain(VOID * arg) { Ext2StartPipeSrv(); Ext2ReportStatus(SERVICE_RUNNING, NO_ERROR, 0); } #define EXT2_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ const GUID name \ = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } EXT2_GUID(GUID_DEVINTERFACE_DISK, 0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2, \ 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); VOID Ext2RegisterDeviceInterface(SERVICE_STATUS_HANDLE handle, GUID guid, HDEVNOTIFY *notify) { DEV_BROADCAST_DEVICEINTERFACE bd; ZeroMemory (&bd, sizeof(bd)); bd.dbcc_size = sizeof(bd); bd.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; bd.dbcc_classguid = guid; *notify = RegisterDeviceNotification(handle, &bd, DEVICE_NOTIFY_SERVICE_HANDLE); } void WINAPI Ext2ServiceEntry(DWORD argc, char**argv) { // register the service control handler ServiceHandle = RegisterServiceCtrlHandlerEx(_T("Ext2Srv"), Ext2CtrlService, NULL); if (ServiceHandle == 0) { return; } // setup standard service state values ServiceStatus.dwServiceType = SERVICE_WIN32; ServiceStatus.dwServiceSpecificExitCode = 0; // report our status to the SCM Ext2ReportStatus(SERVICE_START_PENDING, NO_ERROR, 600); Ext2RegisterDeviceInterface(ServiceHandle, GUID_DEVINTERFACE_DISK, &ServiceNotify); // Now start the service for real Ext2StartMain(NULL); return; } VOID Ext2StartService(VOID *arg) { SERVICE_TABLE_ENTRY Ext2SeriveTable[] = { {_T("Ext2Srv"), (LPSERVICE_MAIN_FUNCTION)Ext2ServiceEntry}, {NULL, NULL} }; // let service control dispatcher start Ext2Mgr StartServiceCtrlDispatcher(Ext2SeriveTable); } #define SERVICE_CMD_LENGTH MAX_PATH int Ext2SetupService(BOOL bInstall) { TCHAR Target[SERVICE_CMD_LENGTH]; SC_HANDLE hService; SC_HANDLE hManager; // get the filename of this executable if (GetModuleFileName(NULL, Target, SERVICE_CMD_LENGTH - 20) == 0) { MessageBox(NULL, _T("Ext2Srv: Unable to install as service"), NULL, MB_OK | MB_ICONERROR); return FALSE; } // open Service Control Manager hManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hManager == NULL) { MessageBox(NULL, _T("Ext2Srv: cannot open Service Control Manager"), NULL, MB_OK | MB_ICONERROR); return FALSE; } if (bInstall) { // now create service entry for Ext2Mgr hService = CreateService( hManager, // SCManager database _T("Ext2Srv"), // name of service _T("Ext2Fsd Service Manager"), // name to display SERVICE_ALL_ACCESS, // desired access SERVICE_WIN32_OWN_PROCESS | // service type SERVICE_INTERACTIVE_PROCESS, SERVICE_AUTO_START, // start type SERVICE_ERROR_NORMAL, // error control type Target, // service's binary NULL, // no load ordering group NULL, // no tag identifier NULL, // dependencies NULL, // LocalSystem account NULL); // no password if (hService == NULL) { DWORD error = GetLastError(); if (error == ERROR_SERVICE_EXISTS) { MessageBox(NULL, _T("Ext2Srv is already registered."), NULL, MB_OK | MB_ICONERROR); } else { MessageBox(NULL, _T("Ext2Srv couldn't be registered."), NULL, MB_OK | MB_ICONERROR); } } else { CloseServiceHandle(hService); // got Ext2Mgr installed as a service MessageBox(NULL, _T("Ext2Srv service was successfully registered. \n\n" "You can modify the default settings and start/stop it from Control Panel.\n" "The service will automatically run the next time when system is restarted.\n"), NULL, MB_OK | MB_ICONINFORMATION); } } else { /* open the service of Pipe Event Engine */ hService = OpenService(hManager, _T("Ext2Srv"), SERVICE_ALL_ACCESS); if (hService != NULL) { SERVICE_STATUS status; // stop the service if (ControlService(hService, SERVICE_CONTROL_STOP, &status)) { while(QueryServiceStatus(hService, &status)) { if (status.dwCurrentState == SERVICE_STOP_PENDING) { Sleep(1000); } else { break; } } if (status.dwCurrentState != SERVICE_STOPPED) { MessageBox(NULL, _T("Ext2Srv: service couldn't be stopped !"), NULL, MB_OK | MB_ICONERROR); } } // remove the service from the SCM if (DeleteService(hService)) { MessageBox(NULL, _T("Ext2Srv: service has been unregistered."), NULL, MB_OK | MB_ICONINFORMATION); } else { DWORD error = GetLastError(); if (error == ERROR_SERVICE_MARKED_FOR_DELETE) { MessageBox(NULL, _T("Ext2Srv: service is already unregistered"), NULL, MB_OK | MB_ICONEXCLAMATION); } else { MessageBox(NULL, _T("Ext2Srv: service could not be unregistered"), NULL, MB_OK | MB_ICONERROR); } } CloseServiceHandle(hService); } } CloseServiceHandle(hManager); return TRUE; } /* * parameter process engine */ int opterr = 1, /* if error message should be printed */ optind = 1, /* index into parent argv vector */ optopt, /* character checked for validity */ optreset; /* reset getopt */ char *optarg; /* argument associated with option */ #define BADCH (int)'?' #define BADARG (int)':' #define EMSG "" /* * getopt -- * Parse argc/argv argument vector. */ int getopt(int argc, char * const argv[], const char *optstring) { static char *place = EMSG; /* option letter processing */ char *oli; /* option letter list index */ if (optreset || *place == 0) { /* update scanning pointer */ optreset = 0; place = argv[optind]; if (optind >= argc || *place++ != '-') { /* Argument is absent or is not an option */ place = EMSG; return (-1); } optopt = *place++; if (optopt == '-' && *place == 0) { /* "--" => end of options */ ++optind; place = EMSG; return (-1); } if (optopt == 0) { /* Solitary '-', treat as a '-' option if the program (eg su) is looking for it. */ place = EMSG; if (strchr(optstring, '-') == NULL) return -1; optopt = '-'; } } else optopt = *place++; /* See if option letter is one the caller wanted */ if (optopt == ':' || (oli = strchr((char *)optstring, optopt)) == NULL) { if (*place == 0) ++optind; if (opterr && *optstring != ':') (void)fprintf(stderr, "unknown option -- %c\n", optopt); return (BADCH); } /* Does this option need an argument? */ if (oli[1] != ':') { /* don't need argument */ optarg = NULL; if (*place == 0) ++optind; } else { /* Option-argument is either the rest of this argument or the entire next argument. */ if (*place) optarg = place; else if (argc > ++optind) optarg = argv[optind]; else { /* option-argument absent */ place = EMSG; if (*optstring == ':') return (BADARG); if (opterr) (void)fprintf(stderr,"option requires an argument - %c\n", optopt); return (BADCH); } place = EMSG; ++optind; } return (optopt); /* return option letter */ } void Ext2Log(DWORD ll, char *fn, int ln, char *format, ... ) { va_list ap = NULL; SYSTEMTIME st = {0}; DWORD w = 0; int i = 0; CHAR s[260] = {0}; if (ll == EXT2_LOG_DUMP) { /* do nothing for MsgDump */ } else { GetLocalTime(&st); sprintf_s(s, 256, "%2.2u:%2.2u:%2.2u (%x): ", st.wHour, st.wMinute, st.wSecond, GetCurrentThreadId()); i = strlen(s); } /* write user message to buffer s */ va_start(ap, format); _vsnprintf(&s[i], 259 - i, format, ap); va_end(ap); printf("%s", s); } INT __cdecl _tmain(INT argc, TCHAR *argv[]) { DWORD rc = 0; BOOL console = FALSE; if (argc >= 2) { if (0 == _tcsicmp(argv[1], _T("/installasservice"))) { return Ext2SetupService(TRUE); } if (0 == _tcsicmp(argv[1], _T("/removeservice"))) { return Ext2SetupService(FALSE); } if (0 == _tcsicmp(argv[1], _T("/startmgr"))) { return Ext2StartMgrAsUser(); } if (argc >= 4) { if (0 == _tcsicmp(argv[1], _T("/mount"))) { Ext2AssignDrvLetter(argv[3], argv[2][0]); return 0; } } else if (argc >= 3) { if (0 == _tcsicmp(argv[1], _T("/umount"))) { Ext2RemoveDrvLetter(argv[2][0]); return 0; } if (0 == _tcsicmp(argv[1], _T("/add"))) { Ext2DrvNotify(argv[2][0], TRUE); Sleep(1000); Ext2DrvNotify(argv[2][0], TRUE); return 0; } if (0 == _tcsicmp(argv[1], _T("/del"))) { Ext2DrvNotify(argv[2][0], FALSE); Sleep(1000); Ext2DrvNotify(argv[2][0], FALSE); return 0; } } } /* enable SE_TCB_NAME privilege */ Ext2EnablePrivilege(SE_TCB_NAME); /* service mode */ Ext2StartService(NULL); return 0; }