A Windows service that start a GUI application launcher
in System Administrator mode. purebasic code.

Download (rename to .rar and use purebasic as password)

Files below: Able.exe service code - SysAdminExec.exe launcher code - .rc resource file - .xml manifest file


Able.exe service code.

; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * A Windows service that can launch a GUI application in System Administrator mode. * ; * * ; * Compiler used: PureBasic 5.62 32/64 - Tested under Windows 7 and Windows 10 * ; * * ; * The exe produced is a service named "Able.exe" that react to those parameters: * ; * /Install ; To install the service so Windows is aware of it. * ; * /Uninstall ; To uninstall the service. It must have been stopped before. * ; * /Status ; Call Service Manager to get the current service state. * ; * /Help ; Show these command line switch * ; * /? ; Show these command line switch * ; * * ; * To install, start a command window as Administrator and type "Able /Install". * ; * You can Start/Stop/Pause/Continue the service via the Service Manager, * ; * to start it click Start button, choose Execute and type "Services.msc". * ; * You can also act at the command prompt: * ; * "Net start Able" * ; * "Net stop Able" * ; * "Net pause Able" * ; * "Net continue Able" * ; * * ; * If you set #Debug to TRUE in code you will need a DebugView utility * ; * running in "Global capture" mode started as Administrator. * ; * This is great to see what the service is doing and for debugging. * ; * You can download one from Microsoft or CobaltFusion: * ; * https://docs.microsoft.com/en-us/sysinternals/downloads/debugview * ; * https://github.com/CobaltFusion/DebugViewPP/releases * ; * See in code for #DelayedStart, #RunAsSystemAdmin, and #AutoStop options. * ; * * ; * Once started, with #RunAsSystemAdmin = #True, * ; * the service, bypassing UAC, will start SysAdminExec.exe in the System Administrator mode, * ; * this is more powerfull than the Administrator mode, be carefull of what you do. * ; * Of course, you may alter the code to start some other applications. * ; * * ; * In Regedit, as System Admin, you will see subkeys like * ; * HKLM\SECURITY\Sam\* (Cache-Policy-Recovery-RXACT-SAM), you won't see this in normal Administrator mode. * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * Update 2020-05-22 (Search code for "2020-05-22") 1.0.0.1 * ; * Added SERVICE_CONTROL_SESSIONCHANGE session change notifications, logon/logoff/sessionLock/unLock * ; * RegisterServiceCtrlHandlerEX() replace RegisterServiceCtrlHandler() * ; * Added a log file, see #Log. * ; * Also many minors enhencements and corrections. * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * Update 2021-07-18 * ; * Minors corrections. * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; Normal folder for Windows service is System32, I do not care about this in the current demo. ; In memory problem, try to start Task Manager / Process (Check All users) / Right click "Able" and stop the process. ; Calling order... ; WinMain() ; serviceInstall /install ; serviceUnInstall /uninstall ; serviceQueryServiceStatus /status ; serviceSetServiceStatus ; ServiceMain ; serviceHandlerEx ; serviceSetServiceStatus ; serviceThreadCreate() ;Start the service ; serviceThread ; RunAsSystemAdmin ; serviceTerminate ; serviceSetServiceStatus EnableExplicit #PB_Compiler_OS = #PB_OS_Windows #PB_Compiler_Processor = #PB_Processor_x64 #PB_Compiler_ExecutableFormat = #PB_Compiler_Console ;#PB_Compiler_Filename = "Able.exe" ;************************************************************************************************************************************************ #Version = "2021-07-18 01:00:01" ;"" * #AppName = "Able" ;Dictionary: able - ?^bl, adjective having enough strength, power or means (To do a thing). * #Log = #True ;#False #True - Write to a .log file, path and name are the same as the service name. * #Debug = #True ;#False #True - See service called procedure and progress in a DebugView utility, must be in CAPTURE GLOBAL mode. * #DelayedStart = #False ;#False #True - To boot faster Windows will start the service after boot up is completely finished. * #RunAsSystemAdmin = #True ;#False #True - Start the GUI application SysAdminExec.exe with the powerfull SystemAdmin privilege. * #AutoStop = #False ;#False #True - Service stop by itself after RunAsSystemAdmin * ;************************************************************************************************************************************************ Declare.l WinMain() Declare serviceInstall() Declare serviceUninstall() Declare.l serviceQueryServiceStatus(sServer.s, sService.s) Declare.s serviceStringType(dwServiceType.l) Declare.s serviceStringStatus(dwServiceStatus.l) Declare.s serviceStringControlIsAccepted(dwControlAccepted.l) Declare.s serviceStringControl(dwServiceControl.l) Declare serviceMain(dwArgs.l, lpszArgv.i) Declare serviceThreadCreate() Declare.l serviceHandlerEx(ControlValue.l, dwEventType.l, lpEventData.l, lpContext.l) Declare serviceThread(idThread.l) Declare serviceSetServiceStatus(CurrentStatus.l, ExitCode.l, SpecificExitCode.l, Checkpoint.l, WaitHint.l) Declare servicePause() Declare serviceResume() Declare serviceStop() Declare serviceStopRaw() Declare serviceTerminate(ErrorCode.l) Declare.l RunAsSystemAdmin(sExeName.s) Declare StdOut(Text.s) Declare.l LogWrite(Text.s) #SERVICES_ACTIVE_DATABASE = "ServicesActive" #MAX_SERVICE_NAME_LEN = 128 #SERVICE_ADAPTER = $4 #SERVICE_RECOGNIZER_DRIVER = $8 #SERVICE_USER_OWN_PROCESS = $50 #SERVICE_USER_SHARE_PROCESS = $60 #SERVICE_INTERACTIVE_PROCESS = $100 #SERVICE_CONTROL_PARAMCHANGE = $06 #SERVICE_CONTROL_NETBINDADD = $07 #SERVICE_CONTROL_NETBINDREMOVE = $08 #SERVICE_CONTROL_NETBINDENABLE = $09 #SERVICE_CONTROL_NETBINDDISABLE = $0A #SERVICE_CONTROL_DEVICEEVENT = $0B #SERVICE_CONTROL_HARDWAREPROFILECHANGE = $0C #SERVICE_CONTROL_POWEREVENT = $0D #SERVICE_CONTROL_SESSIONCHANGE = $0E #SERVICE_CONTROL_PRESHUTDOWN = $0F #SERVICE_CONTROL_TIMECHANGE = $10 #SERVICE_CONTROL_TRIGGEREVENT = $20 #SERVICE_CONTROL_USERMODEREBOOT = $40 #WTS_SESSION_LOGON = $5 #WTS_SESSION_LOGOFF = $6 #WTS_SESSION_LOCK = $7 #WTS_SESSION_UNLOCK = $8 #TokenPrimary = 1 #NameSamCompatible = 2 #WTS_CONSOLE_CONNECT = $1 ;The session identified by lParam was connected to the console terminal or RemoteFX session. #WTS_CONSOLE_DISCONNECT = $2 ;The session identified by lParam was disconnected from the console terminal or RemoteFX session. #WTS_REMOTE_CONNECT = $3 ;The session identified by lParam was connected to the remote terminal. #WTS_REMOTE_DISCONNECT = $4 ;The session identified by lParam was disconnected from the remote terminal. #WTS_SESSION_LOGON = $5 ;A user has logged on to the session identified by lParam. #WTS_SESSION_LOGOFF = $6 ;A user has logged off the session identified by lParam. #WTS_SESSION_LOCK = $7 ;The session identified by lParam has been locked. #WTS_SESSION_UNLOCK = $8 ;The session identified by lParam has been unlocked. #WTS_SESSION_REMOTE_CONTROL = $9 ;The session identified by lParam has changed its remote controlled status. To determine the status, call GetSystemMetrics and check the SM_REMOTECONTROL metric. #WTS_SESSION_CREATE = $A ;Reserved for future use. #WTS_SESSION_TERMINATE = $B ;Reserved for future use. Structure SERVICE_DELAYED_AUTO_START_INFO fDelayedAutostart.l ;Delayed autostart flag EndStructure Structure WTSSESSION_NOTIFICATION cbSize.l dwSessionId.l EndStructure Import "Kernel32.lib" WTSGetActiveConsoleSessionId() ProcessIdToSessionId(ProcessEntry_th32ProcessID.l, *ProcessSessionId.LONG) EndImport Structure GlobalType ;All usefull variables in one place zComputerName.s{#MAX_COMPUTERNAME_LENGTH + 1} zServiceName.s{#MAX_SERVICE_NAME_LEN} zServiceDisplayName.s{#MAX_SERVICE_NAME_LEN} zExeName.s{#MAX_PATH} hServiceStatus.i hInstance.i hEvent.i hThread.i CurrentServiceStatus.l ServiceIsRunning.l ServiceIsPaused.l EndStructure Global *pg.GlobalType ;A single global pointer to a structure of many needed variables WinMain() ;Starting point ;_____________________________________________________________________________ Procedure.l WinMain() Protected g.GlobalType g\zServiceName = #AppName ;Set the service name and display name g\zServiceDisplayName = #AppName + " service" ;Viewed in service manager, 256 char g\hInstance = GetModuleHandle_(0) Protected ComputerNameLen.l = SizeOf(g\zComputerName) GetComputerName_(@g\zComputerName, @ComputerNameLen) ;Use "" for default local service LogWrite(g\zComputerName + " : " + #AppName + " WinMain") *pg = @g ;Set the GlobalType variable pointer GetModuleFileName_(g\hInstance, @*pg\zExeName, #MAX_PATH) ;Get exe full name Protected sCmdLine.s = LCase(ProgramParameter(0)) If FindString(sCmdLine, "/uninstall") serviceUninstall() ElseIf FindString(sCmdLine, "/install") serviceInstall() ElseIf FindString(sCmdLine, "/status") serviceQueryServiceStatus(*pg\zComputerName, *pg\zServiceName) ElseIf FindString(sCmdLine, "/help") | FindString(sCmdLine, "/?") StdOut(#AppName) StdOut(" /install") StdOut(" /uninstall") StdOut(" /status") StdOut(" /help") StdOut(" /?") StdOut(" Net start " + #AppName) StdOut(" Net stop " + #AppName) StdOut(" Net pause " + #AppName) StdOut(" Net continue " + #AppName) StdOut(" Services.msc (For Service Manager)") ElseIf Len(sCmdLine) ;Unknown command StdOut(" Unknown command! (Try /? for help.)") Else ;Command line is empty, Dim ServiceTable.SERVICE_TABLE_ENTRY(1) ;Last entry must be blank ServiceTable(0)\lpServiceName = @g\zServiceName ServiceTable(0)\lpServiceProc = @ServiceMain() LogWrite("WinMain:StartServiceCtrlDispatcher") ;StartServiceCtrlDispatcher_() connects the main thread of a service process to the service control manager, ;which causes the thread to be the service control dispatcher thread for the calling process. ;When Services.msc starts a service, it waits up to 30 sec for the service process to call StartServiceCtrlDispatcher, ;and does not return until all running services in the process have entered the SERVICE_STOPPED If StartServiceCtrlDispatcher_(@ServiceTable(0)) ;Service was started pointing to ServiceMain() and following code will be executed after SERVICE_STOPPED LogWrite("WinMain:StartServiceCtrlDispatcher done : Stopped_OK") Else Protected LastError.l LastError = GetLastError_() ;Might br ERROR_FAILED_SERVICE_CONTROLLER_CONNECT - ERROR_INVALID_DATA - ERROR_SERVICE_ALREADY_RUNNING LogWrite("WinMain:StartServiceCtrlDispatcher not done : Error " + Str(LastError)) ExitProcess_(LastError) EndIf EndIf EndProcedure ;_____________________________________________________________________________ #MaximumLogSize = 10240 ;10k Procedure.l LogWrite(Text.s) Protected FileName.s{#MAX_PATH} Protected ByteWrittenCount.l Protected ByteReadCount.l Protected FileSizeLo.l Protected FileSizeHi.l Protected Ofset.l Protected hFile.i Static Writing.l Protected *Ascii.string Protected *Data Protected *DataSecondHalf If #Debug OutputDebugString_(Text) EndIf If #Log GetModuleFileName_(0, @FileName, #MAX_PATH) FileName = Left(FileName, Len(FileName) - 3) + "log" If Writing = #False Writing = #True hFile = CreateFile_(FileName, #GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ | #FILE_SHARE_WRITE | #FILE_SHARE_DELETE, 0, #OPEN_ALWAYS, #FILE_ATTRIBUTE_NORMAL, 0) If hFile <> #INVALID_HANDLE_VALUE FileSizeLo = SetFilePointer_(hFile, 0, 0, #FILE_END) If FileSizeLo > #MaximumLogSize ;Limit file size SetFilePointer_(hFile, 0, 0, #FILE_BEGIN) *Data = LocalAlloc_(#LMEM_FIXED, FileSizeLo) ReadFile_(hFile, *Data, FileSizeLo, @ByteReadCount, #Null) FileSizeLo = #MaximumLogSize / 2 *DataSecondHalf = *Data + FileSizeLo While PeekB(*DataSecondHalf - 1) <> 10 ;#LF$ *DataSecondHalf + 1 Ofset + 1 : If Ofset > 100 : Break : EndIf ;Try #LF$ for 100 characters Wend FileSizeLo = FileSizeLo - Ofset SetFilePointer_(hFile, 0, 0, #FILE_BEGIN) WriteFile_(hFile, *DataSecondHalf, FileSizeLo, @ByteWrittenCount, 0) LocalFree_(*Data) EndIf *Ascii = Ascii(Text + #CRLF$) WriteFile_(hFile, *Ascii, Len(Text) + 2, @ByteWrittenCount, 0) FreeMemory(*Ascii) SetEndOfFile_(hFile) CloseHandle_(hFile) EndIf Writing = #False EndIf EndIf ProcedureReturn(ByteWrittenCount) EndProcedure ;_____________________________________________________________________________ Procedure.s SesionNotificationString(Notification.l) Protected sNotification.s Select Notification Case #WTS_CONSOLE_CONNECT : sNotification = "WTS_CONSOLE_CONNECT" ;(0x1) The session identified by lParam was connected to the console terminal or RemoteFX session. Case #WTS_CONSOLE_DISCONNECT : sNotification = "WTS_CONSOLE_DISCONNECT" ;(0x2) The session identified by lParam was disconnected from the console terminal or RemoteFX session. Case #WTS_REMOTE_CONNECT : sNotification = "WTS_REMOTE_CONNECT" ;(0x3) The session identified by lParam was connected to the remote terminal. Case #WTS_REMOTE_DISCONNECT : sNotification = "WTS_REMOTE_DISCONNECT" ;(0x4) The session identified by lParam was disconnected from the remote terminal. Case #WTS_SESSION_LOGON : sNotification = "WTS_SESSION_LOGON" ;(0x5) A user has logged on to the session identified by lParam. Case #WTS_SESSION_LOGOFF : sNotification = "WTS_SESSION_LOGOFF" ;(0x6) A user has logged off the session identified by lParam. Case #WTS_SESSION_LOCK : sNotification = "WTS_SESSION_LOCK" ;(0x7) The session identified by lParam has been locked. Case #WTS_SESSION_UNLOCK : sNotification = "WTS_SESSION_UNLOCK" ;(0x8) The session identified by lParam has been unlocked. Case #WTS_SESSION_REMOTE_CONTROL : sNotification = "WTS_SESSION_REMOTE_CONTROL" ;(0x9) The session identified by lParam has changed its remote controlled status. To determine the status, call GetSystemMetrics and check the SM_REMOTECONTROL metric. Case #WTS_SESSION_CREATE : sNotification = "WTS_SESSION_CREATE" ;(0xA) Reserved for future use. Case #WTS_SESSION_TERMINATE : sNotification = "WTS_SESSION_TERMINATE" ;(0xB) Reserved for future use. Default : sNotification = "WTS_SESSION_UNKNOWN" ; EndSelect ProcedureReturn(sNotification + " (0x" + Hex(Notification) + ")") EndProcedure ;______________________________________________________________________________ Procedure.s serviceStringControlIsAccepted(dwControlAccepted.l) Protected sCtrlAccept.s If dwControlAccepted & #SERVICE_ACCEPT_STOP : sCtrlAccept + "SERVICE_ACCEPT_STOP, " : EndIf ;0x001 If dwControlAccepted & #SERVICE_ACCEPT_PAUSE_CONTINUE : sCtrlAccept + "SERVICE_ACCEPT_PAUSE_CONTINUE, " : EndIf ;0x002 If dwControlAccepted & #SERVICE_ACCEPT_SHUTDOWN : sCtrlAccept + "SERVICE_ACCEPT_SHUTDOWN, " : EndIf ;0x004 If dwControlAccepted & #SERVICE_ACCEPT_PARAMCHANGE : sCtrlAccept + "SERVICE_ACCEPT_PARAMCHANGE, " : EndIf ;0x008 If dwControlAccepted & #SERVICE_ACCEPT_NETBINDCHANGE : sCtrlAccept + "SERVICE_ACCEPT_NETBINDCHANGE, " : EndIf ;0x010 If dwControlAccepted & #SERVICE_ACCEPT_PRESHUTDOWN : sCtrlAccept + "SERVICE_ACCEPT_PRESHUTDOWN, " : EndIf ;0x100 If dwControlAccepted = 0 : sCtrlAccept = "Service not started, " : EndIf ;0x000 If Len(sCtrlAccept) = 0 : sCtrlAccept = "SERVICE_ACCEPT_UNKNOWN--" : EndIf ; ProcedureReturn(Left(sCtrlAccept, Len(sCtrlAccept) - 2) + " (0x" + Hex(dwControlAccepted) + ")") EndProcedure ;_____________________________________________________________________________ Procedure.s serviceStringType(dwServiceType.l) Protected sServiceType.s If dwServiceType & #SERVICE_KERNEL_DRIVER : sServiceType + "SERVICE_KERNEL_DRIVER, " : EndIf ;0x001 If dwServiceType & #SERVICE_FILE_SYSTEM_DRIVER : sServiceType + "SERVICE_FILE_SYSTEM_DRIVER, " : EndIf ;0x002 If dwServiceType & #SERVICE_ADAPTER : sServiceType + "SERVICE_ADAPTER, " : EndIf ;0x004 If dwServiceType & #SERVICE_RECOGNIZER_DRIVER : sServiceType + "SERVICE_RECOGNIZER_DRIVER, " : EndIf ;0x008 If dwServiceType & #SERVICE_WIN32_OWN_PROCESS : sServiceType + "SERVICE_WIN32_OWN_PROCESS, " : EndIf ;0x010 If dwServiceType & #SERVICE_WIN32_SHARE_PROCESS : sServiceType + "SERVICE_WIN32_SHARE_PROCESS, " : EndIf ;0x020 If dwServiceType & #SERVICE_USER_OWN_PROCESS : sServiceType + "SERVICE_USER_OWN_PROCESS, " : EndIf ;0x050 If dwServiceType & #SERVICE_USER_SHARE_PROCESS : sServiceType + "SERVICE_USER_SHARE_PROCESS, " : EndIf ;0x060 If dwServiceType & #SERVICE_INTERACTIVE_PROCESS : sServiceType + "SERVICE_INTERACTIVE_PROCESS, " : EndIf ;0x100 If Len(sServiceType) = 0 : sServiceType = "SERVICE_TYPE_UNKNOWN--" : EndIf ; ProcedureReturn(Left(sServiceType, Len(sServiceType) - 2) + " (0x" + Hex(dwServiceType) + ")") EndProcedure ;_____________________________________________________________________________ Procedure.s serviceStringStatus(dwServiceStatus.l) Protected sServiceStatus.s Select dwServiceStatus Case #SERVICE_STOPPED : sServiceStatus = "SERVICE_STOPPED" ;1 The service is not running. Case #SERVICE_START_PENDING : sServiceStatus = "SERVICE_START_PENDING" ;2 The service is starting. Case #SERVICE_STOP_PENDING : sServiceStatus = "SERVICE_STOP_PENDING" ;3 The service is stopping. Case #SERVICE_RUNNING : sServiceStatus = "SERVICE_RUNNING" ;4 The service is running. Case #SERVICE_CONTINUE_PENDING : sServiceStatus = "SERVICE_CONTINUE_PENDING" ;5 The service continue is pending. Case #SERVICE_PAUSE_PENDING : sServiceStatus = "SERVICE_PAUSE_PENDING" ;6 The service pause is pending. Case #SERVICE_PAUSED : sServiceStatus = "SERVICE_PAUSED" ;7 The service is paused. Default : sServiceStatus = "SERVICE_STATUS_UNKNOWN" ; EndSelect ProcedureReturn(sServiceStatus + " (" + Str(dwServiceStatus) + ")") EndProcedure ;_____________________________________________________________________________ Procedure.s serviceStringControl(dwServiceControl.l) Protected sServiceControl.s Select dwServiceControl Case #SERVICE_CONTROL_STOP : sServiceControl = "SERVICE_CONTROL_STOP" ;0x01 Notifies a service that it should stop. Case #SERVICE_CONTROL_PAUSE : sServiceControl = "SERVICE_CONTROL_PAUSE" ;0x02 Notifies a service that it should pause. Case #SERVICE_CONTROL_CONTINUE : sServiceControl = "SERVICE_CONTROL_CONTINUE" ;0x03 Notifies a paused service that it should resume. Case #SERVICE_CONTROL_INTERROGATE : sServiceControl = "SERVICE_CONTROL_INTERROGATE" ;0x04 Notifies a service to report its current status Case #SERVICE_CONTROL_SHUTDOWN : sServiceControl = "SERVICE_CONTROL_SHUTDOWN" ;0x05 Notifies a service to report its current status Case #SERVICE_CONTROL_PARAMCHANGE : sServiceControl = "SERVICE_CONTROL_PARAMCHANGE" ;0x06 Notifies a service that service-specific startup parameters have changed. Case #SERVICE_CONTROL_NETBINDADD : sServiceControl = "SERVICE_CONTROL_NETBINDADD" ;0x07 Notifies a network service that there is a new component for binding. Case #SERVICE_CONTROL_NETBINDREMOVE : sServiceControl = "SERVICE_CONTROL_NETBINDREMOVE" ;0x08 Notifies a network service that a component for binding has been removed. Case #SERVICE_CONTROL_NETBINDENABLE : sServiceControl = "SERVICE_CONTROL_NETBINDENABLE" ;0x09 Notifies a network service that a disabled binding has been enabled. Case #SERVICE_CONTROL_NETBINDDISABLE : sServiceControl = "SERVICE_CONTROL_NETBINDDISABLE" ;0x0A Notifies a network service that one of its bindings has been disabled. Case #SERVICE_CONTROL_DEVICEEVENT : sServiceControl = "SERVICE_CONTROL_DEVICEEVENT" ;0x0B Notifies a service of device events. Case #SERVICE_CONTROL_HARDWAREPROFILECHANGE : sServiceControl = "SERVICE_CONTROL_HARDWAREPROFILECHANGE" ;0x0C Notifies a service that the computer's hardware profile has changed. Case #SERVICE_CONTROL_POWEREVENT : sServiceControl = "SERVICE_CONTROL_POWEREVENT" ;0x0D Notifies a service of system power events. Case #SERVICE_CONTROL_SESSIONCHANGE : sServiceControl = "SERVICE_CONTROL_SESSIONCHANGE" ;0x0E Notifies a service of session change events. Case #SERVICE_CONTROL_PRESHUTDOWN : sServiceControl = "SERVICE_CONTROL_PRESHUTDOWN" ;0x0F Notifies a service that the system will be shutting down. Case #SERVICE_CONTROL_TIMECHANGE : sServiceControl = "SERVICE_CONTROL_TIMECHANGE" ;0x10 Notifies a service that the system time has changed. Case #SERVICE_CONTROL_TRIGGEREVENT : sServiceControl = "SERVICE_CONTROL_TRIGGEREVENT" ;0x20 Notifies a service registered for a service trigger event that the event has occurred. Case #SERVICE_CONTROL_USERMODEREBOOT : sServiceControl = "SERVICE_CONTROL_USERMODEREBOOT" ;0x40 Notifies a service that the user has initiated a reboot. Default : sServiceControl = "SERVICE_CONTROL_UNKNOWN" ; EndSelect ProcedureReturn(sServiceControl + " (0x" + Hex(dwServiceControl) + ")") EndProcedure ;_____________________________________________________________________________ Procedure.l serviceQueryServiceStatus(sServer.s, sService.s) Protected ServiceStat.SERVICE_STATUS Protected hScManager.i Protected hService.i Protected LastError.l LogWrite("serviceQueryServiceStatus") hScManager = OpenSCManager_(@sServer, #SERVICES_ACTIVE_DATABASE, #SC_MANAGER_ENUMERATE_SERVICE) If hScManager hService = OpenService_(hScManager, @sService, #SC_MANAGER_ENUMERATE_SERVICE) LastError = GetLastError_() If hService If QueryServiceStatus_(hService, @ServiceStat) StdOut(" Server: " + sServer) StdOut(" Service: " + sService) StdOut(" CurrentState: " + serviceStringStatus(ServiceStat\dwCurrentState)) StdOut(" ServiceType: " + serviceStringType(ServiceStat\dwServiceType)) StdOut(" ControlsAccepted: " + serviceStringControlIsAccepted(ServiceStat\dwControlsAccepted)) StdOut(" Win32ExitCode: " + Str(ServiceStat\dwWin32ExitCode)) StdOut(" SpecificExitCode: " + Str(ServiceStat\dwServiceSpecificExitCode)) StdOut(" CheckPoint: " + Str(ServiceStat\dwCheckPoint)) StdOut(" WaitHint: " + Str(ServiceStat\dwWaitHint)) EndIf CloseServiceHandle_(hService) Else Select LastError Case #ERROR_SERVICE_DOES_NOT_EXIST : StdOut(" Service " + sService + " : ERROR_SERVICE_DOES_NOT_EXIST") Case #ERROR_INVALID_NAME : StdOut(" Service " + sService + " : ERROR_INVALID_NAME") Case #ERROR_ACCESS_DENIED : StdOut(" Service " + sService + " : ERROR_ACCESS_DENIED") Case #ERROR_INVALID_HANDLE : StdOut(" Service " + sService + " : ERROR_INVALID_HANDLE") Default : StdOut(" Service " + sService + " : ERROR 0x" + Hex(LastError)) EndSelect EndIf CloseServiceHandle_(hScManager) Else StdOut(" serviceQueryServiceStatus:OpenSCManager failed") EndIf ProcedureReturn(ServiceStat\dwCurrentState) EndProcedure ;_____________________________________________________________________________ Procedure.l RunAsSystemAdmin(sExeName.s) ;Launches the given application with full system admin rights bypassing the UAC prompt ;sExeName The name of the application to launch Static zWinSta0.s{20} Protected ProcessInfo.PROCESS_INFORMATION Protected ProcessEntry.PROCESSENTRY32 Protected SecurityAttributes.SECURITY_ATTRIBUTES Protected StartupInf.STARTUPINFO Protected ProcessSessionId.l Protected hUserTokenDup.i Protected hProcess.i Protected hProcessSnapshot.i Protected hProcessToken.i Protected SessionId.l Protected CreationFlags.l Protected RetValProc.l Protected CreateProcessResult.l LogWrite("RunAsSystemAdmin") ;Obtain the currently active session id; every logged on user in the system has a unique session id SessionId = WTSGetActiveConsoleSessionId() ;Get the session-id of the console session: SessionId = 1 Console Active UserName or 0 Services Disconnected "" If SessionId <> #INVALID_HANDLE_VALUE ;Get the ProcessId of the WinLogon that have the same SessionId as the User's dwSessionId ;Obtain the process id of the winlogon process that is running within the currently active session LogWrite("RunAsSystemAdmin:SessionId:OK") hProcessSnapshot = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS | #TH32CS_SNAPTHREAD, #Null) If hProcessSnapshot <> #INVALID_HANDLE_VALUE LogWrite("RunAsSystemAdmin:hProcessSnapshot:OK") ProcessEntry\dwSize = SizeOf(PROCESSENTRY32) RetValProc = Process32First_(hProcessSnapshot, @ProcessEntry) While RetValProc Protected *BStr Protected *BStrData.String *BStr = @ProcessEntry\szExeFile *BStrData.String = @*BStr If LCase(*BStrData\s) = "winlogon.exe" ;May be more than one LogWrite("RunAsSystemAdmin:winlogon:OK") ProcessIdToSessionId(ProcessEntry\th32ProcessID, @ProcessSessionId) ;Process session id RunAsAdmin for winlogon, return nonzero on success If ProcessSessionId = SessionId ;Need WinLogOn sessionId like in TaskManager ;Obtain a handle to the winlogon process LogWrite("RunAsSystemAdmin:ProcessSessionId:OK") hProcess = OpenProcess_(#MAXIMUM_ALLOWED, #False, ProcessEntry\th32ProcessID) If hProcess LogWrite("RunAsSystemAdmin:OpenProcess_:OK") If OpenProcessToken_(hProcess, #TOKEN_DUPLICATE, @hProcessToken) LogWrite("RunAsSystemAdmin:OpenProcessToken_:OK") ;Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser SecurityAttributes\nLength = SizeOf(SECURITY_ATTRIBUTES) ;Copy the access token of the winlogon process, the newly created token will be a primary token If DuplicateTokenEx_(hProcessToken, #MAXIMUM_ALLOWED, @SecurityAttributes, #SecurityIdentification, #TokenPrimary, @hUserTokenDup) LogWrite("RunAsSystemAdmin:DuplicateTokenEx_:OK") ;By default CreateProcessAsUser creates a process on a non-interactive window station, meaning ;the window station has a desktop that is invisible and the process is incapable of receiving ;user input. To remedy this we set the lpDesktop parameter to indicate we want to enable user ;interaction with the new process. zWinSta0 = "winsta0\default" StartupInf\lpDesktop = @zWinSta0 ;Interactive window station parameter; basically this indicates that the process created can display a GUI on the desktop StartupInf\cb = SizeOf(STARTUPINFO) ;Flags that specify the priority and creation method of the process CreationFlags = #NORMAL_PRIORITY_CLASS | #CREATE_NEW_CONSOLE LogWrite("RunAsSystemAdmin:sExeName: " + sExeName) Protected zCurDir.s{#MAX_PATH} If FindString(sExeName, "\") zCurDir = Left(sExeName, Len(sExeName) - FindString(ReverseString(sExeName), "\")) Else EndIf LogWrite("RunAsSystemAdmin:zCurDir: " + zCurDir) LogWrite("RunAsSystemAdmin:CreateProcessAsUser") ;Create a new process in the current user's logon session, Ok if return TRUE ;RegEdit/Admin can't see HKEY_LOCAL_MACHINE\SECURITY\* (Cache-Policy-Recovery-RXACT-SAM) ;RegEdit/SystemAdmin can see HKEY_LOCAL_MACHINE\SECURITY\* (Cache-Policy-Recovery-RXACT-SAM) CreateProcessResult = CreateProcessAsUser_(hUserTokenDup, ;Client's access token #Null, ;File to execute @sExeName, ;Command line @SecurityAttributes, ;Pointer to process SECURITY_ATTRIBUTES @SecurityAttributes, ;Pointer to thread SECURITY_ATTRIBUTES #False, ;Handles are not inheritable CreationFlags, ;Creation flags #Null, ;Pointer to new environment block @zCurDir, ;BYVAL %NULL, _ 'Name of current directory @StartupInf, ;Pointer to STARTUPINFO structure @ProcessInfo) ;Receives information about new process LogWrite("RunAsSystemAdmin:CreateProcessAsUser = " + Str(CreateProcessResult) + " (True = success)") If CreateProcessResult = 0 LogWrite("GetLastError = " + Str(GetLastError_())) EndIf CloseHandle_(hUserTokenDup) EndIf CloseHandle_(hProcessToken) EndIf CloseHandle_(hProcess) EndIf Break ;Job done EndIf EndIf RetValProc = Process32Next_(hProcessSnapshot, @ProcessEntry) Wend CloseHandle_(hProcessSnapshot) EndIf EndIf ProcedureReturn(CreateProcessResult) EndProcedure ;_____________________________________________________________________________ Procedure serviceInstall() Protected ServiceDelayed.SERVICE_DELAYED_AUTO_START_INFO Protected ServiceDesc.SERVICE_DESCRIPTION Protected sServiceDescription.s Protected hServiceControlManager.i Protected hService.i Protected JobDone.l LogWrite("serviceInstall()") hServiceControlManager = OpenSCManager_(@*pg\zComputerName, #Null, #SC_MANAGER_CREATE_SERVICE) If hServiceControlManager hService = CreateService_(hServiceControlManager, @*pg\zServiceName, @*pg\zServiceDisplayName, #SERVICE_ALL_ACCESS, #SERVICE_WIN32_OWN_PROCESS | #SERVICE_INTERACTIVE_PROCESS, #SERVICE_AUTO_START, #SERVICE_ERROR_NORMAL, @*pg\zExeName, #Null, #Null, #Null, #Null, #Null) ;SERVICE_DEMAND_START SERVICE_ERROR_IGNORE If hService ChangeServiceConfig_(hService, #SERVICE_NO_CHANGE, #SERVICE_AUTO_START, #SERVICE_ERROR_NORMAL, #NUL, #NUL, 0, #NUL, #NUL, #NUL, #NUL) sServiceDescription = #AppName + " start a GUI as SYSTEM Administrator." ;1024 bytes ServiceDesc\lpDescription = @sServiceDescription ChangeServiceConfig2_(hService, #SERVICE_CONFIG_DESCRIPTION, @ServiceDesc) If #DelayedStart ;Delayed service start, giving Windows time to breath on starting ServiceDelayed\fDelayedAutostart = #True ChangeServiceConfig2_(hService, #SERVICE_CONFIG_DELAYED_AUTO_START_INFO, @ServiceDelayed) EndIf StdOut("Service install successfull.") JobDone = #True CloseServiceHandle_(hService) Else StdOut("Install - CreateService : Error.") EndIf CloseServiceHandle_(hServiceControlManager) Else StdOut("Install - OpenSCManager : Error.") StdOut("Need to be run as admin.") EndIf ProcedureReturn(JobDone) EndProcedure ;_____________________________________________________________________________ Procedure serviceUnInstall() Protected hServiceControlManager.i Protected hService.i Protected JobDone.l LogWrite("serviceUnInstall()") hServiceControlManager = OpenSCManager_(*pg\zComputerName, #Null, #SC_MANAGER_CREATE_SERVICE) If hServiceControlManager hService = OpenService_(hServiceControlManager, *pg\zServiceName, #SERVICE_ALL_ACCESS) If hService If DeleteService_(hService) StdOut("Uninstall successfull.") JobDone = #True Else StdOut("Uninstall - DeleteService : Error.") EndIf CloseServiceHandle_(hService) Else StdOut("Uninstall - OpenService : Error.") EndIf CloseServiceHandle_(hServiceControlManager) Else StdOut("Uninstall - OpenSCManager : Error.") EndIf ProcedureReturn(JobDone) EndProcedure ;_____________________________________________________________________________ Procedure serviceMain(dwArgs.l, lpszArgv.i) ;dwArgc The number of arguments in the lpszArgv array. ;lpszArgv The null-terminated argument strings passed to the service by the call to the StartService function ; that started the service. If there are no arguments, this parameter can be NULL. ; Otherwise, the first argument (lpszArgv[0]) is the name of the service, followed ; by any additional arguments (lpszArgv[1] through lpszArgv[dwArgc-1]). ; If the user starts a manual service using the Services snap-in from the Control Panel, ; the strings for the lpszArgv parameter come from the properties dialog box ; for the service (from the Services snap-in, right-click the service entry, click Properties, ; and enter the parameters in Start parameters.) ;All initialization tasks are done in ServiceMain() when the service is started. Protected SecurityAttribute.SECURITY_ATTRIBUTES Protected RetVal.l Protected dwContext.l ;User defined custom value LogWrite("serviceMain()") If OpenLibrary(123, "AdvApi32.dll") *pg\hServiceStatus = CallCFunctionFast(GetFunction(123, "RegisterServiceCtrlHandlerExW"), @*pg\zServiceName, @ServiceHandlerEx(), dwContext) If *pg\hServiceStatus ;Did Not work ;Startup is pending If serviceSetServiceStatus(#SERVICE_START_PENDING, #NO_ERROR, 0, 1, 5000) LogWrite("serviceMain : SERVICE_START_PENDING") ;Create the termination event *pg\hEvent = CreateEvent_(@SecurityAttribute, #True, #False, "") If *pg\hEvent ;Service startup is still pending If serviceSetServiceStatus(#SERVICE_START_PENDING, #NO_ERROR, 0, 2, 1000) RetVal = serviceThreadCreate() ;Start the service If RetVal ;Service did start If serviceSetServiceStatus(#SERVICE_RUNNING, #NO_ERROR, 0, 0, 0) ;Service is now running ;Wait for the signal to end LogWrite("serviceMain : Service thread started : SERVICE_RUNNING : WaitForSingleObject") WaitForSingleObject_(*pg\hEvent, #INFINITE) EndIf EndIf EndIf EndIf EndIf EndIf EndIf ServiceTerminate(GetLastError_()) CloseLibrary(123) EndProcedure ;_____________________________________________________________________________ Procedure serviceThreadCreate() Protected SecurityAttribute.SECURITY_ATTRIBUTES Protected idThread.l LogWrite("serviceThreadCreate()") *pg\hThread = CreateThread_(SecurityAttribute, 0, @ServiceThread(), 0, 0, idThread) If *pg\hThread ;The thread start OK *pg\ServiceIsRunning = #True ;Set the global to running ProcedureReturn(#True) EndIf EndProcedure ;_____________________________________________________________________________ Procedure.l serviceHandlerEx(ControlValue.l, dwEventType.l, lpEventData.l, lpContext.l) LogWrite("serviceHandler(Received request for " + serviceStringControl(ControlValue) + ")") Select ControlValue Case #SERVICE_CONTROL_STOP, #SERVICE_CONTROL_SHUTDOWN, #CTRL_SHUTDOWN_EVENT If *pg\ServiceIsPaused ;Resuming before ending serviceSetServiceStatus(#SERVICE_CONTINUE_PENDING, #NO_ERROR, 0, 1, 1000) ;Tell the SCM that we are resuming ServiceResume() ;Resume the service *pg\CurrentServiceStatus = #SERVICE_RUNNING ;Set the current state EndIf *pg\CurrentServiceStatus = #SERVICE_STOP_PENDING ;Set global status serviceSetServiceStatus(#SERVICE_STOP_PENDING, #NO_ERROR, 0, 1, 5000) ServiceStop() Case #SERVICE_CONTROL_PAUSE ;0x2 Service should pause. If (*pg\ServiceIsRunning <> #False) And (*pg\ServiceIsPaused = #False) ;Running And Not paused serviceSetServiceStatus(#SERVICE_PAUSE_PENDING, #NO_ERROR, 0, 1, 1000) ;Tell the SCM that we are pausing ServicePause() ;Pause it *pg\CurrentServiceStatus = #SERVICE_PAUSED ;Set the current state EndIf Case #SERVICE_CONTROL_CONTINUE ;0x3 Service should resume If (*pg\ServiceIsRunning <> #False) And (*pg\ServiceIsPaused <> #False) ;Running and paused serviceSetServiceStatus(#SERVICE_CONTINUE_PENDING, #NO_ERROR, 0, 1, 1000) ;Tell the SCM that we are resuming ServiceResume() ;Resume the service *pg\CurrentServiceStatus = #SERVICE_RUNNING ;Set the current state EndIf Case #SERVICE_CONTROL_INTERROGATE ;0x4 Service should report its current status to the control manager ;Simply return NO_ERROR; the SCM is aware of the current state of the service. ProcedureReturn(#NO_ERROR) ;A return value is needed else the command line "Net Start" will be erratic Case #SERVICE_CONTROL_SESSIONCHANGE Protected *pWtSessionNotification.WTSSESSION_NOTIFICATION *pWtSessionNotification = lpEventData LogWrite("SERVICE_CONTROL_SESSIONCHANGE : " + SesionNotificationString(dwEventType) + ", SessionId: " + *pWtSessionNotification\dwSessionId) Select dwEventType Case #WTS_SESSION_LOGON ;0x5 ;LogWrite("WTS_SESSION_LOGON SessionId: " + *pWtSessionNotification\dwSessionId) Case #WTS_SESSION_LOGOFF ;0x6 ;LogWrite("WTS_SESSION_LOGOFF SessionId: " + *pWtSessionNotification\dwSessionId) Case #WTS_SESSION_LOCK ;0x7 ;LogWrite("WTS_SESSION_LOGON SessionId: " + *pWtSessionNotification\dwSessionId) Case #WTS_SESSION_UNLOCK ;0x8 ;LogWrite("WTS_SESSION_UNLOCK SessionId: " + *pWtSessionNotification\dwSessionId) ;WTS_CONSOLE_CONNECT (0x1) The session identified by lParam was connected To the console terminal Or RemoteFX session. ;WTS_CONSOLE_DISCONNECT (0x2) The session identified by lParam was disconnected from the console terminal Or RemoteFX session. ;WTS_REMOTE_CONNECT (0x3) The session identified by lParam was connected To the remote terminal. ;WTS_REMOTE_DISCONNECT (0x4) The session identified by lParam was disconnected from the remote terminal. ;WTS_SESSION_LOGON (0x5) A user has logged on To the session identified by lParam. ;WTS_SESSION_LOGOFF (0x6) A user has logged off the session identified by lParam. ;WTS_SESSION_LOCK (0x7) The session identified by lParam has been locked. ;WTS_SESSION_UNLOCK (0x8) The session identified by lParam has been unlocked. ;WTS_SESSION_REMOTE_CONTROL (0x9) The session identified by lParam has changed its remote controlled status. To determine the status, CALL GetSystemMetrics And check the SM_REMOTECONTROL metric. ;WTS_SESSION_CREATE (0xA) Reserved For future use. ;WTS_SESSION_TERMINATE (0xB) Reserved For future use. ;lParam [IN] The identifier of the session. EndSelect EndSelect serviceSetServiceStatus(*pg\CurrentServiceStatus, #NO_ERROR, 0, 0, 0) ProcedureReturn(#NO_ERROR) EndProcedure ;_____________________________________________________________________________ Procedure serviceThread(idThread.l) ;Here goes the service's job... If #RunAsSystemAdmin LogWrite("-") ;Show UserNameEx and UserName Protected zUserName.s{#UNLEN} Protected UserNameLen.l = #UNLEN GetUserNameEx_(#NameSamCompatible, @zUserName, @UserNameLen) LogWrite("UserNameEx: " + zUserName) GetUserName_(@zUserName, @UserNameLen) LogWrite("UserName: " + zUserName + " <<<<<<<<<<<<<<<<<<< Should be 'System' (System Administrator).") ;Call SysAdminExec.exe Protected FullNameExe.s{#MAX_PATH} FullNameExe = GetPathPart(*pg\zExeName) + "SysAdminExec.exe" ;Set full path name LogWrite("serviceThread(RunAsSystemAdmin(" + FullNameExe + ")") RunAsSystemAdmin(FullNameExe) Sleep_(2000) EndIf If #AutoStop ServiceStopRaw() ;Used when a service want To End by itself after his job is done Else Repeat LogWrite("serviceThread() running " + FormatDate("%hh:%ii:%ss", Date())) Sleep_(2000) ForEver EndIf EndProcedure ;_____________________________________________________________________________ Procedure serviceSetServiceStatus(CurrentStatus.l, ExitCode.l, ServiceSpecificExitCode.l, Checkpoint.l, WaitHint.l) LogWrite("serviceSetServiceStatus(" + serviceStringStatus(CurrentStatus) + ")") Protected ServiceStatus.SERVICE_STATUS ServiceStatus\dwServiceType = #SERVICE_WIN32_OWN_PROCESS ;Setup the UDT. ServiceStatus\dwCurrentState = CurrentStatus If CurrentStatus = #SERVICE_START_PENDING ServiceStatus\dwControlsAccepted = #SERVICE_ACCEPT_SESSIONCHANGE Else ServiceStatus\dwControlsAccepted = #SERVICE_ACCEPT_STOP | #SERVICE_ACCEPT_PAUSE_CONTINUE | #SERVICE_ACCEPT_SHUTDOWN | #SERVICE_ACCEPT_SESSIONCHANGE EndIf If ServiceSpecificExitCode = 0 ServiceStatus\dwWin32ExitCode = ExitCode Else ServiceStatus\dwWin32ExitCode = #ERROR_SERVICE_SPECIFIC_ERROR EndIf ServiceStatus\dwServiceSpecificExitCode = ServiceSpecificExitCode ServiceStatus\dwCheckPoint = Checkpoint ServiceStatus\dwWaitHint = WaitHint If SetServiceStatus_(*pg\hServiceStatus, @ServiceStatus) ProcedureReturn(#True) Else ;Something went wrong, so stop the service ServiceStop() EndIf EndProcedure ;_____________________________________________________________________________ Procedure servicePause() LogWrite("servicePause() " + FormatDate("%hh:%ii:%ss", Date())) *pg\ServiceIsPaused = #True ;Set the global indicating that we are paused SuspendThread_(*pg\hThread) EndProcedure ;_____________________________________________________________________________ Procedure serviceResume() LogWrite("serviceResume() " + FormatDate("%hh:%ii:%ss", Date())) *pg\ServiceIsPaused = #False ;Set the global indicating that we are not paused ResumeThread_(*pg\hThread) EndProcedure ;_____________________________________________________________________________ Procedure serviceStop() LogWrite("Service thread stopping at " + FormatDate("%hh:%ii:%ss", Date())) *pg\ServiceIsRunning = #False ;Set the global flag indicating that the service is not running SetEvent_(*pg\hEvent) ;Set the event so the service will stop EndProcedure ;_____________________________________________________________________________ Procedure serviceStopRaw() ;Use when a service want to end by itself Protected ServiceStat.SERVICE_STATUS Protected hServiceControlManager.i Protected hService.i LogWrite("serviceStopRaw()") hServiceControlManager = OpenSCManager_(*pg\zComputerName, #Null, #SC_MANAGER_CREATE_SERVICE) If hServiceControlManager hService = OpenService_(hServiceControlManager, @*pg\zServiceName, #SERVICE_ALL_ACCESS) If hService ControlService_(hService, #SERVICE_CONTROL_STOP, @ServiceStat) EndIf CloseServiceHandle_(hServiceControlManager) EndIf EndProcedure ;_____________________________________________________________________________ Procedure serviceTerminate(ErrorCode.l) LogWrite("serviceTerminate()") If *pg\hEvent CloseHandle_(*pg\hEvent) EndIf If *pg\hServiceStatus serviceSetServiceStatus(#SERVICE_STOPPED, ErrorCode, 0, 0, 0) EndIf If *pg\hThread CloseHandle_(*pg\hThread) EndIf EndProcedure ;_____________________________________________________________________________ Procedure StdOut(Text.s) Protected CharDone.l Protected Reserved.l WriteConsole_(GetStdHandle_(#STD_OUTPUT_HANDLE), Text + #CRLF$, Len(Text) + 2, CharDone, Reserved) EndProcedure ;_____________________________________________________________________________ ; ; IDE Options = PureBasic 5.72 (Windows - x64) ; ExecutableFormat = Console ; CursorPosition = 720 ; FirstLine = 841 ; Markers = 645,689 ; EnableAsm ; EnableThread ; EnableXP ; EnableAdmin ; UseIcon = wmploc.DLL.024.ico ; Executable = Able.exe ; DisableDebugger ; CompileSourceDirectory ; Compiler = PureBasic 5.72 (Windows - x64) ; IncludeVersionInfo ; VersionField0 = 1.0.0.1 ; VersionField1 = 1.0.0.1 ; VersionField2 = Able ; VersionField3 = Able ; VersionField4 = 1.0.0.1 ; VersionField5 = 1.0.0.1 ; VersionField6 = Service to start a GUI as SYSTEM Administrator ; VersionField7 = Able ; VersionField8 = Able ; VersionField9 = 2020 ; VersionField10 = 2020 ; EnableUnicode

SysAdminExec.exe launcher code.

; ******************************************************************************************** ; SysAdminExec.exe - A application launcher For the Able Windows service. * ; * ; Detect if User is Administrator or System-Administrator, application icon will follow. * ; Use an .ini file for size, position, and record the last 150 exe launched. * ; Use a mutex for single instance and set self foreground. * ; * ; Enable messages reception from non elevated applications, * ; this may be done with Drag-and-Drop or via the command line. * ; * ; ******************************************************************************************** EnableExplicit #PB_Compiler_ExecutableFormat = #PB_Compiler_Executable #PB_Compiler_IsMainFile = 1 #WM_COPYGLOBALDATA = $0049 #ButtonExec = 101 #ComboExeNameList = 201 #StaticAdminInfo = 301 #CRYPT_STRING_HEXRAW = $C #SECURITY_NT_AUTHORITY = 5 Macro LoWord(WordWord) : (WordWord&$ffff) : EndMacro Macro HiWord(WordWord) : ((WordWord>>16)&$ffff) : EndMacro ;_____________________________________________________________________________ Procedure.s AsciiToUnicode(sAscii.s) Protected CharCount.l Protected sUnicode.s CharCount = lstrlen_(sAscii) ;Get dual bytes character count sUnicode = Space(CharCount * 2) ;Initialize string MultiByteToWideChar_(#CP_ACP, #Null, sAscii, CharCount, @sUnicode, @CharCount) ProcedureReturn(sUnicode) EndProcedure ;_____________________________________________________________________________ Procedure.s FileDataGet(sFileName.s) Protected hFile.l Protected FileSizeLo.l Protected FileSizeHi.l Protected ReturnCount.l Protected sFileData.s hFile = CreateFile_(sFileName, #GENERIC_READ, #FILE_SHARE_READ, #Null, #OPEN_EXISTING, #FILE_ATTRIBUTE_NORMAL, #Null) If hFile <> #INVALID_HANDLE_VALUE FileSizeLo = GetFileSize_(hFile, @FileSizeHi) sFileData = Space(FileSizeLo) ReadFile_(hFile, @sFileData, FileSizeLo, @ReturnCount, #Null) CloseHandle_(hFile) ProcedureReturn(AsciiToUnicode(sFileData)) EndIf EndProcedure ;_____________________________________________________________________________ Procedure.l FileDataSet(sFileName.s, sFileData.s) Protected hFile.l Protected WrittenCount.l Protected *aFileData hFile = CreateFile_(sFileName, #GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ, #Null, #CREATE_ALWAYS, #FILE_ATTRIBUTE_NORMAL, #Null) If hFile <> #INVALID_HANDLE_VALUE *aFileData = Ascii(sFileData) WriteFile_(hFile, *aFileData, Len(sFileData), @WrittenCount, #Null) FreeMemory(*aFileData) SetEndOfFile_(hFile) CloseHandle_(hFile) If WrittenCount = Len(sFileData) ProcedureReturn(#True) EndIf EndIf EndProcedure ;_____________________________________________________________________________ Procedure.l IsUserAdmin() Protected NtAuthority.SID_IDENTIFIER_AUTHORITY ;6bytes Protected *AdministratorsGroup Protected zAutoriteNT.s{#UNLEN} Protected zSysName.s{#UNLEN} Protected zCurrentUser.s{#UNLEN} Protected SidAccountType.l Protected AutoriteNtLen.l Protected SysNameLen.l Protected IsMember.l Protected AdminLevel.l ;IsUserAnAdmin api may not be there in future Windows release, so doing it following way. NtAuthority\value[5] = #SECURITY_NT_AUTHORITY ;SECURITY_NT_AUTHORITY = 5 If AllocateAndInitializeSid_(@NtAuthority, 2, #SECURITY_BUILTIN_DOMAIN_RID, #DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, @*AdministratorsGroup) If OpenLibrary(125, "AdvApi32.dll") If CallCFunctionFast(GetFunction(125, "CheckTokenMembership"), #Null, *AdministratorsGroup, @IsMember) If IsMember ;Is Administrator + System Administrator ;Get SystemAdministatot locale name, will differ with different language ;SID: S-1-5-18 - Local System - "System" - "Syst�me" AUTORITE NT - A service account that is used by the operating system. Dim SidArray.b(11) SidArray.b(0) = 1 : SidArray.b(1) = 1 : SidArray.b(0) = 1 : SidArray.b(7) = 5 : SidArray.b(8) = 18 ;Chr(1, 1, 0, 0, 0, 0, 0, 5, 18, 0, 0, 0) SysNameLen = SizeOf(zSysName) AutoriteNTLen = SizeOf(zAutoriteNT) If LookupAccountSid_(#Null, @SidArray(0), @zSysName, @SysNameLen, @zAutoriteNT, @AutoriteNtLen, @SidAccountType) ;ok if true Protected UserNameLen.l = #UNLEN GetUserName_(@zCurrentUser, @UserNameLen) ;A SysAdm will get locale-System as name If zCurrentUser = zSysName ;User is SystemAdmin AdminLevel = 2 ;System-Administrator Else AdminLevel = 1 ;Administrator only EndIf EndIf EndIf EndIf EndIf CloseLibrary(125) FreeSid_(*AdministratorsGroup) EndIf ProcedureReturn(AdminLevel) EndProcedure ;_____________________________________________________________________________ Procedure.l DoShellExecuteEx(hParent.l, zVerb.s, zFile.s, zParam.s, zPath.s, dwShow.l) Protected ShellInfo.SHELLEXECUTEINFO If LCase(Right(zFile, 4)) <> ".lnk" ShellInfo\lpVerb = @zVerb Else ShellInfo\lpVerb = #Null EndIf ShellInfo\cbSize = SizeOf(ShellInfo) ShellInfo\hWnd = hParent ShellInfo\lpFile = @zFile ShellInfo\lpParameters = @zParam ShellInfo\lpDirectory = @zPath ShellInfo\nShow = dwShow ShellInfo\hInstApp = #Null ShellInfo\lpIdList = #Null ShellInfo\lpClass = #Null ShellInfo\hkeyClass = #Null ShellInfo\dwHotKey = #Null ShellInfo\hProcess = #Null ShellInfo\fMask = #SEE_MASK_FLAG_DDEWAIT ShellExecuteEx_(ShellInfo) If ShellInfo\hInstApp > 32 ProcedureReturn(ShellInfo\hProcess) EndIf EndProcedure ;_____________________________________________________________________________ Procedure ComboboxDuplicateRemove(hComboBox.i) Protected index.l For index = 0 To SendMessage_(hComboBox, #CB_GETCOUNT, 0, 0) - 2 Protected sItem.s = Space(SendMessage_(hComboBox, #CB_GETLBTEXTLEN, index, 0)) SendMessage_(hComboBox, #CB_GETLBTEXT, index, @sItem) Protected Found.l = SendMessage_(hComboBox, #CB_FINDSTRINGEXACT, index, @sItem) ;#CB_ERR = -1 If Found > index SendMessage_(hComboBox, #CB_DELETESTRING, Found, 0) index - 1 ;Since the item is deleted, all subsequent item will be shifted up, so decrement index to avoid missing one item EndIf Next For index = 150 To SendMessage_(hComboBox, #CB_GETCOUNT, 0, 0) - 1 ;Limit list to 150 items SendMessage_(hComboBox, #CB_DELETESTRING, index, 0) Next EndProcedure ;_____________________________________________________________________________ Procedure WndProc(hWnd, uMsg, wParam, lParam) Protected pPaint.PAINTSTRUCT Protected tRect.RECT Protected *CreateStruct.CREATESTRUCT Protected LogicalFont.LOGFONT Protected NonClient.NONCLIENTMETRICS Protected ClientSize.SizeL Protected sIniFileData.s Protected ComboboxItem.s, ComboboxItems.s Protected index.l Protected hDC.i Static hInstance.i Static hStaticAdminInfo.i Static hComboExeNameList.i Static hButtonExec.i Static hFont.i Static sIniFileName.s Static hIcon.i Select uMsg Case #WM_CREATE *CreateStruct = lParam ;Just for the fun of using pointers to get hInstance from CreateWindowEx_() hInstance = *CreateStruct\lpCreateParams ;Or hInstance = GetModuleHandle_(0) ;Enable message reception from non elevated application ChangeWindowMessageFilter_(#WM_DROPFILES, #MSGFLT_ADD) ChangeWindowMessageFilter_(#WM_COPYDATA, #MSGFLT_ADD) ChangeWindowMessageFilter_(#WM_COPYGLOBALDATA, #MSGFLT_ADD) ;Get default Windows font NonClient\cbSize = SizeOf(NONCLIENTMETRICS) SystemParametersInfo_(#SPI_GETNONCLIENTMETRICS, SizeOf(NONCLIENTMETRICS), @NonClient, 0) LogicalFont = NonClient\lfMessageFont hFont = CreateFontIndirect_(LogicalFont) ;Usually "Segoe UI", 9 ;Create static hStaticAdminInfo = CreateWindowEx_(#WS_EX_TRANSPARENT, "Static", "I am Not SystemAdministrator, nor Administrator.", #WS_CHILD | #WS_VISIBLE | #SS_CENTER | #SS_CENTERIMAGE , 20, 5, 500, 15, hWnd, #StaticAdminInfo, hInstance, 0) SendMessage_(hStaticAdminInfo, #WM_SETFONT, hFont, #True) ;Create ComboBox hComboExeNameList = CreateWindowEx_(#WS_EX_CLIENTEDGE , "ComboBox", "", #WS_CHILD | #WS_VISIBLE | #WS_TABSTOP | #CBS_DROPDOWN | #CBS_AUTOHSCROLL | #CBS_HASSTRINGS, 20, 30, 500, 225, hWnd, #ComboExeNameList, hInstance, 0) SendMessage_(hComboExeNameList, #WM_SETFONT, hFont, #True) SendMessage_(hComboExeNameList, #CB_SETMINVISIBLE, 25, 0) Protected hwndEdit.i = FindWindowEx_(hComboExeNameList, 0, "Edit", #Null) ;Get Combobox Edit handle SendMessage_(hwndEdit, #EM_SETCUEBANNER, 01, @"RunAs - Accept Drag&Drop - Accept CommandLine") ;Cue stay if control have focus, #CB_SETCUEBANNER don't ;Create execute button hButtonExec = CreateWindowEx_(#WS_EX_LEFT, "Button", "Start this executable", #WS_CHILD | #WS_VISIBLE | #WS_TABSTOP, 20, 65, 500, 25, hWnd, #ButtonExec, hInstance, 0) SendMessage_(hButtonExec, #WM_SETFONT, hFont, #True) ;Verify User/Admin/SysAdmin level Protected.l AdminLevel = IsUserAdmin() If AdminLevel = 1 SetWindowText_(hStaticAdminInfo, "I am Administrator but not SystemAdministrator.") hIcon = LoadImage_(hInstance, "#102", #IMAGE_ICON, 32, 32, #LR_DEFAULTCOLOR) ElseIf AdminLevel = 2 SetWindowText_(hStaticAdminInfo, "I am Administrator and SystemAdministrator.") hIcon = LoadImage_(hInstance, "#103", #IMAGE_ICON, 32, 32, #LR_DEFAULTCOLOR) Else SetWindowText_(hStaticAdminInfo, "I am not Administrator, nor SystemAdministrator.") hIcon = LoadImage_(hInstance, "#101", #IMAGE_ICON, 32, 32, #LR_DEFAULTCOLOR) EndIf ;Set icon SendMessage_(hWnd, #WM_SETICON, #ICON_SMALL, hIcon) SendMessage_(hWnd, #WM_SETICON, #ICON_BIG, hIcon) ;Read ini file sIniFileName = ProgramFilename() sIniFileName = Left(sIniFileName, Len(sIniFileName) - 3) + "ini" sIniFileData = FileDataGet(sIniFileName) If Len(sIniFileData) For index = 1 To CountString(sIniFileData, #CRLF$) + 1 ComboboxItem = StringField(sIniFileData, index, #CRLF$) If Left(ComboboxItem, 16) = "WindowPlacement=" If OpenLibrary(0126, "Crypt32.dll") Protected WinPla.WindowPlacement Protected WinPlaSize.l ComboboxItem = RTrim(Mid(ComboboxItem, 17)) WinPlaSize = SizeOf(WindowPlacement) CallCFunctionFast(GetFunction(0126, "CryptStringToBinaryW"), @ComboboxItem, ;Convert from hexadecimal text WinPlaSize * 2, #CRYPT_STRING_HEXRAW, @WinPla, @WinPlaSize, 0, 0) CloseLibrary(0126) WinPla\showCmd = #SW_RESTORE SetWindowPlacement_(hWnd, WinPla) EndIf Break Else SendMessage_(hComboExeNameList, #CB_ADDSTRING, index - 1, ComboboxItem) EndIf Next Else ;Some defaults if no ini SendMessage_(hComboExeNameList, #CB_ADDSTRING, index - 1, @"RegEdit.exe") SendMessage_(hComboExeNameList, #CB_ADDSTRING, index - 1, @"Explorer.exe") SendMessage_(hComboExeNameList, #CB_ADDSTRING, index - 1, @"NotePad.exe") EndIf SendMessage_(hComboExeNameList, #CB_SETCURSEL, 0, 0) ;Select first item in list ;Command-line If OpenLibrary(0127, "Shell32.dll") Protected ArgumentCount.l Protected *Argument.string = CallCFunction(0127, "CommandLineToArgvW", GetCommandLine_(), @ArgumentCount) CloseLibrary(0127) Protected pMem.i = *Argument For index = 01 To ArgumentCount - 1 ;Bypass first *Argument and enumerate subsequents *Argument = *Argument + SizeOf(*Argument) ;Point to the next argument SendMessage_(hComboExeNameList, #CB_INSERTSTRING, 0, *Argument\s) Next LocalFree_(pMem) ComboboxDuplicateRemove(hComboExeNameList) SendMessage_(hComboExeNameList, #CB_SETCURSEL, 0, 0) ;Select first item in list EndIf ProcedureReturn(0) Case #WM_COMMAND Select LoWord(wParam) ;Control id Case #ButtonExec, #IDOK ;Execute program from combobox If (HiWord(wParam) = #BN_CLICKED) Or (HiWord(wParam) = 1) Protected.s zFile.s{#MAX_PATH} Protected.s zParam.s{#MAX_PATH} Protected.s zPath.s{#MAX_PATH} Protected.s zVerb.s{30} Protected.s Duplicate Protected.i hParent Protected.l dwShow Protected.l TextLen TextLen = SendMessage_(hComboExeNameList, #WM_GETTEXTLENGTH, 0, 0) If TextLen hParent = GetDesktopWindow_() zVerb = "open" SendMessage_(hComboExeNameList, #WM_GETTEXT, TextLen + 1, @zFile) ;Get item DoShellExecuteEx(hParent, zVerb, zFile, zParam, zPath, #SW_SHOWNORMAL) ;Execute it SendMessage_(hComboExeNameList, #CB_INSERTSTRING, 0, zFile) ;Insert item in position zero ComboboxDuplicateRemove(hComboExeNameList) SendMessage_(hComboExeNameList, #CB_SETCURSEL, 0, 0) ;Item zero become the current selection EndIf EndIf Case #IDCANCEL ;Escape key PostMessage_(hWnd, #WM_SYSCOMMAND, #SC_CLOSE, 0) EndSelect Case #WM_DROPFILES ;Dropped files on self window Protected zFileName.s{#MAX_PATH} Protected.i hDrop Protected.l DroppedFileCount Protected.l Looper hDrop = wParam DroppedFileCount = DragQueryFile_(hDrop, $FFFFFFFF, 0, 0) For Looper = 0 To DroppedFileCount - 1 DragQueryFile_(hDrop, Looper, @zFileName, SizeOf(zFileName)) SendMessage_(hComboExeNameList, #CB_INSERTSTRING, 0, @zFileName) If Looper = DroppedFileCount - 1 SendMessage_(hComboExeNameList, #WM_SETTEXT, Len(zFileName), zFileName) ;Write edit part of combo EndIf Next DragFinish_(hDrop) ;Releases drop memory allocated by Windows ComboboxDuplicateRemove(hComboExeNameList) Case #WM_CTLCOLORSTATIC If lParam = hStaticAdminInfo SetTextColor_(WPARAM, #Yellow) SetBkMode_(WPARAM, #TRANSPARENT) ProcedureReturn(GetStockObject_(#NULL_BRUSH)) ;Set background transparent EndIf Case #WM_ERASEBKGND ;DrawGradient, hDC in wParam Protected rcFill.RECT Protected rcClient.RECT Protected Increment.f Protected hBrush.i Protected BandIndex GetClientRect_(WindowFromDC_(wParam), rcClient) Increment = rcClient\Bottom / 100 For BandIndex = 0 To 99 SetRect_(rcFill, 0, BandIndex * Increment, rcClient\Right + 1, (BandIndex + 1) * Increment) hBrush = CreateSolidBrush_(RGB(10, 50, 192 - BandIndex)) FillRect_(wParam, rcFill, hBrush) DeleteObject_(hBrush) Next Case #WM_LBUTTONDOWN ;Client area dialog drag via click down simulation on caption If wParam = #MK_LBUTTON SendMessage_(hComboExeNameList, #CB_SHOWDROPDOWN, #False, 0) SendMessage_(hWnd, #WM_NCLBUTTONDOWN, #HTCAPTION, #Null) EndIf Case #WM_GETMINMAXINFO ;Window size limit Protected *MinMaxInfoPtr.MINMAXINFO *MinMaxInfoPtr = lParam *MinMaxInfoPtr\ptMinTrackSize\x = 400 ;Limit minimum width *MinMaxInfoPtr\ptMinTrackSize\y = 135 ;Limit minimum height *MinMaxInfoPtr\ptMaxTrackSize\y = 135 ;Limit maximum height Case #WM_SIZE ;Window resizing If wParam <> #SIZE_MINIMIZED ClientSize\cx = LoWord(lParam) ClientSize\cy = HiWord(lParam) MoveWindow_(hStaticAdminInfo, 5, 5, ClientSize\cx - 10, 14, #False) MoveWindow_(hComboExeNameList, 5, 25, ClientSize\cx - 10, 14, #False) MoveWindow_(hButtonExec, 5, 65, ClientSize\cx - 10, 24, #False) InvalidateRect_(hWnd, #Null, #True) : UpdateWindow_(hWnd) EndIf Case #WM_CLOSE PostMessage_(hWnd, #WM_QUIT, 0, 0) Case #WM_DESTROY ;Save filename list to ini file For index = 0 To SendMessage_(hComboExeNameList, #CB_GETCOUNT, 0, 0) - 1 ComboboxItem = Space(SendMessage_(hComboExeNameList, #CB_GETLBTEXTLEN, index, 0)) SendMessage_(hComboExeNameList, #CB_GETLBTEXT, index, @ComboboxItem) sIniFileData = sIniFileData + ComboboxItem + #CRLF$ Next Protected sHexText.s If OpenLibrary(0128, "Crypt32.dll") ;Convert WinPla to hexa-decimal text WinPla\length = SizeOf(WindowPlacement) GetWindowPlacement_(hWnd, @WinPla) Protected HexTextLen.l = SizeOf(WindowPlacement) * 4 + 4 sHexText = Space(HexTextLen) CallCFunctionFast(GetFunction(0128, "CryptBinaryToStringW"), WinPla, SizeOf(WinPla), #CRYPT_STRING_HEXRAW, @sHexText, @HexTextLen) CloseLibrary(0128) sHexText = "WindowPlacement=" + Left(sHexText, Len(sHexText) - 02) EndIf FileDataSet(sIniFileName, sIniFileData + sHexText) ;Clean-up DestroyIcon_(hIcon) DeleteObject_(hFont) PostQuitMessage_(0) EndSelect ProcedureReturn(DefWindowProc_(hWnd, uMsg, wParam, lParam)) EndProcedure ;_____________________________________________________________________________ Define wce.WndClassEx Define WindowSize.Sizel Define msg.msg Define AppName.s Define CommandLine.s Define hWnd.i Define hInstance.i AppName = "SysAdminExec" hInstance = GetModuleHandle_(0) ;Using a mutex to allow only one instance of this app Define dwMutex.l = 2006162257 ;YYMMDDHHMM Define sMutex.s = "2006162257" ;MaxStringLen is #MAX_PATH, no "\", case sensitive Define hMutex.i = CreateMutex_(#Null, 0, sMutex) If GetLastError_() = #ERROR_ALREADY_EXISTS ;App is already running Define hTry.i = GetForegroundWindow_() ;Start search with the foreground Window While hTry If GetWindowLongPtr_(hTry, #GWL_USERDATA) = dwMutex ;Found it If IsWindowVisible_(hTry) ;Ignore hidden windows If IsIconic_(hTry) ShowWindow_(hTry, #SW_RESTORE) ;UnMinimize if needed Else ShowWindow_(hTry, #SW_SHOW) SetForegroundWindow_(hTry) EndIf Break ;Job done, exit loop EndIf EndIf hTry = GetWindow_(hTry, #GW_HWNDNEXT) Wend End(#ERROR_ALREADY_EXISTS) EndIf ;See SetWindowLongPtr_() below wce\cbSize = SizeOf(WNDCLASSEX) wce\STYLE = #CS_HREDRAW | #CS_VREDRAW wce\lpfnWndProc = @WndProc() wce\cbClsExtra = 0 wce\cbWndExtra = 0 wce\hInstance = hInstance wce\hIcon = 0 wce\hIconSm = 0 wce\hCursor = LoadCursor_(#Null, #IDC_ARROW) wce\hbrBackground = 0 wce\lpszMenuName = 0 wce\lpszClassName = @AppName RegisterClassEx_(@wce) WindowSize\cx = 540 WindowSize\cy = 140 ;Create a window using the registered class hWnd = CreateWindowEx_(#WS_EX_LEFT | #WS_EX_ACCEPTFILES, AppName, ;Window class name AppName, ;Window caption #WS_OVERLAPPEDWINDOW, ;Window style (GetSystemMetrics_(#SM_CXSCREEN) - WindowSize\cx) / 2, ;Center position x (GetSystemMetrics_(#SM_CYSCREEN) - WindowSize\cy) / 2, ;Centr position y WindowSize\cx, ;x size WindowSize\cy, ;y size #HWND_DESKTOP, ;Parent window handle 0, ;Window menu handle hInstance, ;Program instance handle hInstance) ;Creation parameters SetWindowLongPtr_(hWnd, #GWL_USERDATA, dwMutex) ;This window have unique USERDATA number ShowWindow_(hWnd, #SW_SHOWDEFAULT) UpdateWindow_(hWnd) While GetMessage_(Msg, 0, 0, 0) ;<> #WM_QUIT If IsDialogMessage_(hWnd, Msg) = #False TranslateMessage_(Msg) ;TranslateMessage translates virtual-key messages into character messages. DispatchMessage_(Msg) EndIf Wend End msg\wParam ;_____________________________________________________________________________ ; ; IDE Options = PureBasic 5.72 (Windows - x64) ; CursorPosition = 50 ; FirstLine = 42 ; EnableAsm ; EnableXP ; UseIcon = ieframe.dll.108.ico ; Executable = SysAdminExec.exe ; DisableDebugger ; CompileSourceDirectory ; IncludeVersionInfo ; AddResource = SysAdminExec.rc ; EnableUnicode

.rc resource file.

0x65 ICON "ieframe.dll.108.ico" // 101 blue 0x66 ICON "imageres.dll.073.ico" // 102 blue yellow 0x67 ICON "wlanpref.dll.011.ico" // 103 blue yellow green red #define IDR_MANIFEST 1 // EXE = 1, DLL = 2. #define RT_MANIFEST 24 // Side-by-Side Assembly Manifest. MAKEINTRESOURCE(24) IDR_MANIFEST RT_MANIFEST "SysAdminExec.xml"

.xml manifest file.

<?xml version='1.0' encoding='UTF-8' standalone='yes'?> <assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'> <assemblyIdentity version='1.0.0.0' processorArchitecture='*' name='Company.Product.Name' type='win32' /> <description></description> <!-- Common controls - Theme section --> <dependency> <dependentAssembly> <assemblyIdentity type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*' /> </dependentAssembly> </dependency> <!-- Version - Compatibility section for Program Compatibility Assistant (PCA) --> <compatibility xmlns='urn:schemas-microsoft-com:compatibility.v1'> <application> // Windows XP and Windows Vista ignore this manifest section <!-- Windows Vista --> <supportedOS Id='{e2011457-1546-43c5-a5fe-008deee3d3f0}'/> <!-- Windows 7 --> <supportedOS Id='{35138b9a-5d96-4fbd-8e2d-a2440225f93a}'/> <!-- Windows 8 --> <supportedOS Id='{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}'/> <!-- Windows 8.1 Needed to report GetVersionEx 6.3 instead of 8.2--> <supportedOS Id='{1f676c76-80e1-4239-95bb-83d0f6d0da78}'/> <!-- Windows 10.0 Needed to report GetVersionEx 10.0 instead of 6.2--> <supportedOS Id='{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}'/> </application> </compatibility> <!-- DpiAware & long path section --> <!-- <dpiAware>true</dpiAware> --> // <asmv3:application xmlns:asmv3='urn:schemas-microsoft-com:asm.v3'> // <asmv3:windowsSettings xmlns='http:\x2F\x2Fschemas.microsoft.com/SMI/2005/WindowsSettings'> // \x2F = 47 = '/' // <dpiAware>false</dpiAware> // <path:longPathAware>true</path:longPathAware> // </asmv3:windowsSettings> // </asmv3:application> <asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"> <asmv3:windowsSettings xmlns:dpi="http://schemas.microsoft.com/SMI/2005/WindowsSettings" xmlns:path="http://schemas.microsoft.com/SMI/2016"> <dpi:dpiAware>True</dpi:dpiAware> <path:longPathAware>true</path:longPathAware> </asmv3:windowsSettings> </asmv3:application> <!-- Trustinfo section - Run as --> <asmv3:trustInfo xmlns:asmv3='urn:schemas-microsoft-com:asm.v3'> <asmv3:security> <asmv3:requestedPrivileges> <!-- level='asInvoker' level='highestAvailable' level='requireAdministrator' --> <!-- DO not put anything betwen <asmv3:requestedExecutionLevel and </asmv3:requestedPrivileges> --> <!-- OR you will get "The operating system denied access to the specified file." --> <asmv3:requestedExecutionLevel level='asInvoker' uiAccess='false' /> </asmv3:requestedPrivileges> </asmv3:security> </asmv3:trustInfo> </assembly>
hosted by awardspace andrew sun's syntax highlighter