mirror of
				https://github.com/bobranten/Ext4Fsd.git
				synced 2025-10-30 21:38:31 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			579 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			579 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <Ext2Srv.h>
 | |
| 
 | |
| 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;
 | |
| } |