You are here

Adding ExecAsUser

17 posts / 0 new
Last post
demon.devin
demon.devin's picture
Offline
Last seen: 4 years 4 months ago
Developer
Joined: 2007-08-02 09:04
Adding ExecAsUser

I think there should be an option for programs that need to be executed as a normal/standard user but require the launcher to have administrative rights. If you don't know what I'm talking about you can read up on this topic here.

So within the AppNameLauncher.ini file there could be a new key such as [Activate]ExecAsUser=true and we could add/change the code in the PortableApps.comLauncher.nsi file to something like this (I pulled directly from the code in my variant of PAL and edited/removed minor/unrelated code but the concept is just the same in essence):

;= I use !searchparse because we need to set this definition 
;= but need it to be set outside of a function/section.
!searchparse /ignorecase /noerrors /file `${PACKAGE}\App\AppInfo\Launcher\${AppID}.ini` `ExecAsUser=` ExecAsUser

;= Sets/Unsets the define
!if ! ${ExecAsUser} == "" ;= If it is not empty
	!if ${ExecAsUser} == true ;= If it is true
		!define /REDEF ExecAsUser ;= already set to true but we redefine ExecAsUser to nullify it
	!else if ${ExecAsUser} == false ;= If it is false
		!undef ExecAsUser ;= than we undefine it
	!else ;= If anything other than true or false
		;= the following !error instruction will stop the compiler 
		;= and will show the message that follows
		!error "The key 'ExecAsUser' has an invalid value."
		!error "Please review the Launcher.ini file and be sure it has a true/false value set."
	!endif
!else ;= otherwise it must be empty
	!error "ExecAsUser is empty but needs a true/false value! Please check the Launcher.ini file.
	!error "If this feature isn't needed, than delete the key."
!endif

;= Code to include the StdUtils plugin using the concept I shared on GitHub
;= https://github.com/PortableApps/Launcher/issues/4#issuecomment-330439105
;= See footnote 3
!ifdef ExecAsUser
	!include StdUtils.nsh
	!ifndef PLUGINSDIR
		!define PLUGINSDIR
		!AddPluginDir Plugins
	!endif
!endif
;= This could also be another feature to add this plugin which gives a developer
;= the ability to use this plugin within the custom.nsh file without using ExecAsUser
!ifdef StdUtils 
	!ifndef ExecAsUser
		!include StdUtils.nsh
		!ifndef PLUGINSDIR
			!define PLUGINSDIR
			!AddPluginDir Plugins
		!endif
	!endif
!endif

;= The main codebase for the ExecAsUser proposal
Function Execute           ;{{{1
        ${EmptyWorkingSet}
        ClearErrors
        ${ReadLauncherConfig} $0 Launch HideCommandLineWindow
        ${If} $0 == true
            StrCpy $ExecString "$ExecString $Parameters"
            ExecDos::exec /TOSTACK $ExecString
            Pop $0
        ${Else}
            ${IfNot} ${Errors}
            ${AndIf} $0 != false
                ${InvalidValueError} [Launch]:HideCommandLineWindow $0
            ${EndIf}
            ${If} $WaitForProgram != false
                !ifdef ExecAsUser ;= This should have been set earlier in the script using !searchparse
                    ${ConfigReads} `${CONFIG}` ExecAsAdmin= $0 ;= See footnote 1 below for why this is here.
                    ${If} $0 == true
                        StrCpy $ExecString "$ExecString $Parameters"
                        ExecWait $ExecString
                    ${Else}
                        ${StdUtils.ExecShellAsUser} $0 "$ExecString" "" "$Parameters" ;= Pick-a-boo!
                        ${EmptyWorkingSet}
                        Sleep 1000
                        ${GetFileName} $ProgramExecutable $1
                        ${EmptyWorkingSet}
                        ${Do}
                            ${ProcessWaitClose} $1 -1 $R9
                            ${IfThen} $R9 > 0 ${|} ${Continue} ${|}
                        ${LoopWhile} $R9 > 0
                    ${EndIf}
                !else
                    ExecWait $ExecString
                !endif
            ${Else}
                !ifdef ExecAsUser
                    ${StdUtils.ExecShellAsUser} $0 "$ExecString" "" "$Parameters" ;= I see you! =)
                !else
                    Exec $ExecString
                !endif
            ${EndIf}
        ${EndIf}
        ${If} $WaitForProgram != false
            ClearErrors
            ${ReadLauncherConfig} $0 Launch WaitForOtherInstances
            ${If} $0 == true
            ${OrIf} ${Errors}
                ${GetFileName} $ProgramExecutable $1
                ${EmptyWorkingSet}
                ${Do}
                    !ifdef Sleep ;= This is another idea I have.. See footnote 2 below for why this is here.
                        Sleep ${Sleep} ;= ${Sleep} is set earlier in the script and is a number in milliseconds 
                    !endif
                    ${ProcessWaitClose} $1 -1 $R9
                    ${IfThen} $R9 > 0 ${|} ${Continue} ${|}
                    StrCpy $0 1
                    ${Do}
                        !ifdef Sleep
                            Sleep ${Sleep}
                        !endif
                        ClearErrors
                        ${ConfigReadS} `${LAUNCHER}` WaitForEXE$0= $2
                        ${IfThen} ${Errors} ${|} ${ExitDo} ${|}
                        ExpandEnvStrings $2 $2
                        ${ProcessWaitClose} $2 -1 $R9
                        ${IfThen} $R9 > 0 ${|} ${ExitDo} ${|}
                        IntOp $0 $0 + 1
                    ${Loop}
                ${LoopWhile} $R9 > 0
            ${ElseIf} $0 != false
                ${InvalidValueError} [Launch]:WaitForOtherInstances $0
            ${EndIf}
        ${EndIf}
    !endif
FunctionEnd

The above code makes use of the StdUtils plug-in which is the self proclaimed Swiss Army Knife for NSIS. For more information on this plugin, you can visit this page: http://nsis.sourceforge.net/StdUtils_plug-in

Footnote 1
I have added ${ConfigReads} `${CONFIG}` ExecAsAdmin= $0 as a means to check the user configuration file for the key ExecAsAdmin for a true value. This is just a fail safe measure for the end-user who would still like for the application to run elevated even when we've set ExecAsUser to be true..

Footnote 2
If you read the above code and came across Sleep ${Sleep}, this is just another idea I used within my version of PAL where I define a number in milliseconds for an application if it has the ability to restart itself. For example, Notepad++ when it is installing/upgrading plugins. This little bit of code will make the launcher sleep for X amount of seconds before continuing on and checking if the main application's process has stopped.

Footnote 3 | Edit
I forgot to add a means to include this plugin. You'll notice I've added the same concept as I suggested on one of the open issues on the GitHub project. This snippet will add the plugin folder inside ../Other/Source/Plugins which can hold all the necessary plugins needed for use within PAL. Here's the direct link to what I'm referring to: https://github.com/PortableApps/Launcher/issues/4#issuecomment-330439105

John T. Haller
John T. Haller's picture
Offline
Last seen: 9 hours 5 min ago
AdminDeveloperModeratorTranslator
Joined: 2005-11-28 22:21
Use Case?

Which app would be a use case for this in our context? I understand the use case when doing a local installer (which requires admin) as opposed to launching the app itself (which runs as user) but I can't think of any apps we'd release that require admin for the launcher but not for the app itself. The only time we permit a portable app to require admin rights is if it normally requires them to run (disk defrag, direct drive write utilities, system level utilities, HKLM reg cleaners, etc).

Sometimes, the impossible can become possible, if you're awesome!

demon.devin
demon.devin's picture
Offline
Last seen: 4 years 4 months ago
Developer
Joined: 2007-08-02 09:04
GitHub Desktop, Discord, 7-Zip, etc.

I make use of this feature in my recent builds of GitHub Desktop Portable, Discord Portable, and even 7-Zip Portable. I know it to be good practice to run an application with user privileges. Unless an application is designed to be run exclusively by system administrators (like you said, defragmentation programs or other programs like anti-viruses), it should be run with the least privileges possible. With that in mind, my launchers for the aforementioned PAFs are the ones which need elevated privileges and not the application itself.

More often than not, when a new program is installed, that's when the installer prompts for privileges, right? After installation has completed, you won't see a UAC prompt for programs such as 7-Zip or Discord. Since we are essentially "installing" and "uninstalling" the software which we're making portable, this makes sense. For example--this is just an example to illustrate my point--I know your version of 7-Zip runs with normal privileges so this cannot happen using the version distributed here. However, in my 7-Zip I give the end-user the option to set if they'd like the extra functionality from having the launcher run with elevated rights. Keeping that in mind, let's say someone accidentally tries to use 7-Zip's file manager to delete a system folder. If he's running uninhabited than he/she probably just broke something in the system. However, using this concept we can prevent this from happening and still use the extra perks of having the launcher run elevated while launching the main program under standard rights.

Moreover, we can write to certain places such as HKLM registry hives and the ProgramData/AllUsersAppData folder. Applications like 7-Zip only reads from HKLM during runtime (reading icon settings, etc.) which doesn't require admin rights. Reading from ProgramData works the same way unless of course an application is trying to write which this feature would not apply. Remember, I've also added the extra user configuration setting for advanced users to override this feature by setting [AppNamePortable]ExecAsAdmin to true.

daemon.devin

John T. Haller
John T. Haller's picture
Offline
Last seen: 9 hours 5 min ago
AdminDeveloperModeratorTranslator
Joined: 2005-11-28 22:21
Specific Example

I'd still like a specific example of a release-able app that we'd do this for. 7-Zip works without issue without needing any admin rights in the launcher. What specific functionality would we need in the 7-Zip Portable launcher to bug the user for admin rights every time they launch the app?

Sometimes, the impossible can become possible, if you're awesome!

demon.devin
demon.devin's picture
Offline
Last seen: 4 years 4 months ago
Developer
Joined: 2007-08-02 09:04
Give It A Try...

I kindly implore you to give my version of 7-Zip Portable a good once over at least. I'd much rather let my work speak for itself John. I'm getting a lot of positive feedback from people who have tried it out. Even users at TPFC seem to be happy with it and someone had asked if I tried discussing with you about integrating my version with the official release here at PA.c. Plus, looking at the GitHub project's statistics, I can only imagine it will continue to grow in popularity.

Here's just one of my download mirrors I've made available from my website:
https://www.upload.ee/files/7461979/7-ZipPortable_16.04_Rev._3.paf.exe.html

At the time of posting this message, the download count from this Upload.ee link was at 30. Both Rev. 1 and Rev. 2 had a combined total of over 100+ downloads. I'm only saying this so you can see that there must be a reason people are attracted to this version.

It has been my experience that most of the people that use my portables (or any PAF for that matter) are using them on their home PCs. Which means they've got administrative privileges and will love to benefit from cool extra features like file type associations or junction support for quicker launch speeds. Now I'm not forgetting about the people that are making use of my PAFs on machines with limited access rights. For example, my Discord PAF uses junctions for better handling of it's settings but if a user is on a machine which only allows him/her standard rights, it will automatically fallback on copying/moving files/directories. That's not all, I've given the user the ability to disable the UAC prompt if he/she wanted in the user configuration file. So if they're knowingly going into a PC with limited access rights, let's say like at a local library, they can change this setting before hand and skip junction support entirely.

I've implemented the same features from Discord in my GitHub Desktop Portable. Plus, another feature I've allowed added in my GitHub Desktop Portable is support for protocols. So if a user has GitHub Desktop Portable running and they're browsing GitHub, they can click on the green "Clone" button and select "Open in Desktop" and voila! It works with out a hitch.

EDIT:
If a user doesn't mind a minor UAC prompt asking for administrative rights in order to gain extra functionality from a portable, why would we deny them that? We can still give them the ability to disable the UAC prompt as I have already done so successfully. I'm currently working on code to allow drag-and-drop features in some portables. Now wouldn't that be a nifty little feature?

daemon.devin

John T. Haller
John T. Haller's picture
Offline
Last seen: 9 hours 5 min ago
AdminDeveloperModeratorTranslator
Joined: 2005-11-28 22:21
Majority of Users, Specific Functionality, etc

Around half of our users do not have admin rights on the PC they're using the apps on. In addition to portable users, lots of users use these apps locally on a work or corporate/university-owned PC that they only have user rights on. So, for these users, you'd be bugging them by default for something they can't give you. Quite a few people consider admin-requiring apps to not be portable.

I'd asked for specific functionality of an app and I still haven't gotten an answer on that. File associations don't require admin rights (you can do them in HKCU). But that's moot as I'd already stated we won't be bringing file associations to PAL. File association logic in hundreds of separate launcher EXEs would be really messy to fix bugs in. And it will kinda mess up PCs with Windows 8/10 (the majority of users) unless the user is using the apps locally and nothing else due to the way modern Windows handles associations. There's also the additional point I'd already made that file associations only when an app is running aren't particularly useful. Most users want associations so they can just double-click a file or click a file in another app and have the appropriate app launch automatically.

The other suggestion of junctions isn't something we'll be pursuing. After a crash, junctions leave a PC in a much worse state than simply moving a folder from APPDATA\AppName to APPDATA\AppName-BackupByPortableAppName. Especially for users who don't understand junctions (read: most users). Even if we did go that route, it would only be useful to a user on their own PC where they are using the app on an external drive, which is a minority of users. Users using the apps locally on their C: drive or from a standard cloud synced directory (all of which are C: by default) don't experience much lag from copying files/folders since they're going from C: to C: unless they are particularly huge. None of the released apps in our directory fit that bill.

I don't yet see any apps we'd consider releasing that require ExecAsUser unless you're thinking some specific private apps with custom code or that require HKLM keys present but don't require admin to run (which aren't considered portable and eligible for release). Were you thinking for this specific instance?

Sometimes, the impossible can become possible, if you're awesome!

demon.devin
demon.devin's picture
Offline
Last seen: 4 years 4 months ago
Developer
Joined: 2007-08-02 09:04
Fine.

I'm starting to feel exhausted trying to win your approval John. Remember, you were the one who asked me about my ideas and yet everything I've shared here or at GitHub has been disregarded or ignored. Which makes it like I'm wasting my invaluable time. The only thing that actually got picked up was the implementation of allowing the user to have the ability to choose what variant of an application they'd like to install and I wasn't even trying to make that proposal to begin with. I found that quite funny because I wasn't trying to push for that at all; that was just for my own personal archive.

I've given you guys countless means of expanding your codebase. I'm beginning to really feel like I'm over extending myself for no reason but to see myself speak. The only reason I haven't taken my knowledge and findings elsewhere is because I'm very brand loyal. Not that there is anywhere else to go but I could start my own project if I want to. I do not want to do that nor do I have the means to do so either. I believe in this website. I've invested over a decade of my time learning this craft and refining my skill-set to make PAFing more than just the pathetic, meek bullshit you guys are mildly standing behind here. Remember when I was developing AIMP Portable? I knew nothing about NSIS at all back then. When you made it a candidate for an official release, I was over joyed and found myself a new hobby. Then I saw your edits to my version of AIMP, where you used a binary of SQLite to handle the changes in drive letters. I was blown away but it was at that moment I realized that all applications are different and if I want to be a good developer than I'm going to need to learn more than just what Chris Morgan's documentation had outlined.

Would you have gone out of your way to disregard these ideas if Chris Morgan had suggested them? Is that why he just went over your head and did what he did setting up the building blocks of PAL all on his own? I'm sure you had a say in it's conception but you said it yourself that you don't know the inner workings of PAL as much as you should. Why wasn't the Services or the RegDLLs segments ever completed? Did you tell Chris to stop developing that area for some reason? He started such a wonderful and brilliant framework for making portable applications and yet it never went anywhere which shouldn't have happened. This place should have exploded and became the only resource for portable applications.

I don't yet see any apps we'd consider releasing that require ExecAsUser unless you're thinking some specific private apps with custom code or that require HKLM keys present but don't require admin to run (which aren't considered portable and eligible for release). Were you thinking for this specific instance?

No but yes, of course! It's obvious to me that my thoughts about moving PAL forward far exceeds how you feel about moving forward with the project. I'm thinking about the bigger picture and the future but you're making it clear that it is your job even though you're hiding behind an open source policy. I believe you're a very good team leader and can oversee managing great projects which this one should have been over 5 years ago. You've probably been to a couple workshops on product oversight and leadership building skills because you've done an exemplary job so far; and I mean that John. You've proven this fact to me because you're able to see the bigger picture even when I couldn't which is why I'm trying so goddamn hard to stand behind your brand and make it so much more than what it is right now. Being a staunch and avid supporter of PA.c, it pains me to try and continue following this project as there are so many people turning away because of other solutions like virtualization software.

I've already had a similar discussion with another forum moderator here and he helped me to see some aspects that you're having to deal with which is why I'm still trying to work with you my friend. Please, allow me to paint you a picture John. I think that the hardcore developers that know what they're doing should have extensive knowledge in other areas of portable apps, not just in the PAF standard. For instance, if someone comes along and asks about a virtualized application (I've known this to happen), we should know the answer or at least pretend to know. In the beginning when I found/joined PA.c, I thought the name "PortableApps.com" meant all aspects in the art of portablizing software, not just one standard way. Hear me out.. I believe the only way to make a program portable is "PAFing" it.. I feel it is the only way to go and is the best and ultimate means to making a program portable but the head developers should know the competition's dark-arts in a sense too. Does that make sense?

This place should be the flagship when it comes to portable applications. Don't get me wrong because this website is the name in portable applications but it should already be that on a much larger scale than where we're at right now. I say we because I still believe that this is an open source project. So when I suggest something as an addition to PAL, please think of the real life applications it can have as this concept I'm actually pushing for is a damn good one. We should st least be trying to have features which can compare to other solutions like Cameyo or Turbo Studio which is why this place is not going to higher places like it should.

Around half of our users do not have admin rights on the PC they're using the apps on. In addition to portable users, lots of users use these apps locally on a work or corporate/university-owned PC that they only have user rights on. So, for these users, you'd be bugging them by default for something they can't give you. Quite a few people consider admin-requiring apps to not be portable.

Your user base isn't just what you say it is buddy. You should be trying to accommodate anyone you can. As I said before, the PAFs can be made to not run with admin rights by default. The option can be set for the users who can benefit from the extra advantages of running elevated if they decide to do so.

daemon.devin

John T. Haller
John T. Haller's picture
Offline
Last seen: 9 hours 5 min ago
AdminDeveloperModeratorTranslator
Joined: 2005-11-28 22:21
Code Features for the sake of code features

You seem to be advocating for the addition of features to the codebase which would not be of use to the majority of users. You seem to be advocating for them despite the logistical issues with making them work and the support issues with continuing to support them. The reason I am asking you the things I am and positing the situations I am is that I am hoping you will specifically point out a situation where my knowledge of what you're proposing is lacking or a user scenario I have overlooking. Proposing a feature for the sake of a feature is not the proper way to expand a code base or increase functionality for end users.

Take, for example, your desire to add file associations to PAL. I've outlined the reasons why we consider this to be unworkable. From the fact that it would make support difficult, especially when needing to fix bugs in hundreds of launchers as opposed to a single location (implementing associations within the platform). To the fact that file associations would be partially broken for the majority of users since most of our users are on Windows 8/10 and file associations can't be cleanly handled on these operating systems. To the fact that file associations would be far less useful than users desire in this scenario due to the fact that they wouldn't work unless the app is already running. For some reason, you seem keen on glossing over all of these technical and logistical issues and continue to demand adding the feature for the sake of the feature. Why is this? You did the same thing with my points on junctions and how they impact the user experience. You can't advocate for something and then completely side step all of the issues that will arise from your implementation when they are brought up.

It helps to keep in mind that running a project and continuing to have it be useful for end users and a large community is as much about what you don't add as it is what you do. Many a project has been brought down by adding dozens of niche features that hurt the user experience for the majority of users. Or that add lots of work on the development and support end that is not balance by the feature added or the number of users benefited.

Please take the time to consider and address the numerous issues with your suggested additions with respect to the overall userbase, maintainability of the full infrastructure of the hundreds of affected launchers, etc.

Remember, I'm not opposed to implementing specific features even if they're only used in niche instances unless they will cause issues with the overall project (time, support, user experience, money, etc).

To use an example... what if, for instance, we expanded PAL to allow junctions but only for advanced users when they set specific options that they were fully aware of. No extra settings within PAL itself in terms of the launcher INI (other than turning it on), just an advanced way to handle DirectoryMove so that it would use a junction instead of an actual file move. Then we could let the user set it for that specific launcher (via an AppNamePortable.ini directive next to AppNamePortable.exe saying UseJunctionsForDirectoryMoves=true) or for all launchers (via an environment variable called UsePortableApps.comLauncherUseJunctionsForDirectoryMoves=true). We'd, of course, need to specifically check for existing junctions to avoid stepping on them, still handle backing up the existing directories, possibly leave a note text file explaining what's up in the parent of the junction directory in case of crash and a user trying to manually fix things, include a warning that this could cause unintended side effects as junctions can be a bit wonky in Windows, etc. And it would be disabled by default but available for specific advanced users who want to enable it on their own PC (and are in the minority who would benefit from the speed boost) and understand the risks. Is this something along the lines of what you were thinking?

Sometimes, the impossible can become possible, if you're awesome!

demon.devin
demon.devin's picture
Offline
Last seen: 4 years 4 months ago
Developer
Joined: 2007-08-02 09:04
Thank You!

I'm not demanding anything here; lets just get that out of the way but I do stand firmly behind the things I'm representing. What you said in you're last paragraph is exactly why you're the boss. This is why I'm still trying to be apart of this whole thing. That's all I was looking for. I've only thought of half of what you've outlined. Just to clarify, I wasn't trying to suggest file associations anymore per your concerns. The only reason I kept mentioning it was to illustrate key points. As far as it being unworkable, in the case of using it in PAL, you're absolutely correct. I've tried working on a way to create a segment which could be used to handle this idea but fail short. This can only be handled with custom code because every application is different which is why you see me do this in my Notepad++ and 7-Zip. To my defense, I'm running on Windows 8.1 and associations work flawlessly however I've had a couple people running on Windows 10 tell me that it's not working for them. Thus, making it a moot point now.

As far as junctions.. junctions is an older technology and probably shouldn't be considered anyway. I can understand your thoughts about trying to avoid making use of this feature. The biggest issue that you've conveyed to me and understandably so is when a user has a bad exit or a system crashes. To that, I have no answer for. I haven't done enough research to speak on that particular scenario so I've halted any further usage of junctions on my end. Besides, you've already made it pretty clear and told me that you're not going to pursue the idea anyway.

I only suggest things I believe should be considered. I only come up with these suggestions after I've done some researching and the applicable testing which proves successful. I have a small group of friends (or colleagues depending on how you look at it) that I work with and they too have similar input which heavily sway the direction I go in my development of my version of PAL. If it works for me than that means it should work for others too but you're helping me see that is not always the case. So my apologies in that respect. I guess you can consider me an advocate for the niche-case, advanced user. A man of the minority (not racial you sickos ..lol.) people.

Back on topic, I do not have any other specific examples to give you but that doesn't mean this should be overlooked either. What you said about being used for private applications is one prime example for why this should be made available. If your concerns are that people might be using these advanced ideas to make commercial programs portable than you're right but you can't deny something just because of one bad seed. Alcohol has a hefty death toll but is still very much legal. I know, that was a horrible example to use but you can see my point. I've got a lot of commercial applications in which I've made portable for my own personal use. I've just PAFed Komodo IDE 10 by ActiveState after winning an Innovation Award at PHPClasses.org for one of my PHP scripts and this was my reward in return. I'm sure other users of PAL are doing the same thing with their programs as well who can benefit from things like this. I speak for these people not those who are for warez and the like so don't misconstrued what I'm speaking on please.

daemon.devin

demon.devin
demon.devin's picture
Offline
Last seen: 4 years 4 months ago
Developer
Joined: 2007-08-02 09:04
More on Junctions

I use a binary made available by Mark Russinovich.
https://docs.microsoft.com/en-us/sysinternals/downloads/junction

Here are the junctions macros including a function to find the root directory of both the portable and local directories. I'm assuming you can read the code so I do not need to explain what's happening line by line.

Function Root
	!macro _Root _PATH _RETURN
		Push `${_PATH}`
		Call Root
		Pop ${_RETURN}
	!macroend
	!define Root `!insertmacro _Root`
	Exch $0
	Push $1
	Push $2
	Push $3
	StrCpy $1 $0 2
	StrCmp $1 '\\' +5
	StrCpy $2 $1 1 1
	StrCmp $2 ':' 0 +16
	StrCpy $0 $1
	Goto +15
	StrCpy $2 1
	StrCpy $3 ''
	IntOp $2 $2 + 1
	StrCpy $1 $0 1 $2
	StrCmp $1$3 '' +9
	StrCmp $1 '' +5
	StrCmp $1 '\' 0 -4
	StrCmp $3 '1' +3
	StrCpy $3 '1'
	Goto -7
	StrCpy $0 $0 $2
	StrCpy $2 $0 1 -1
	StrCmp $2 '\' 0 +2
	StrCpy $0 ''
	Pop $3
	Pop $2
	Pop $1
	Exch $0
FunctionEnd

!define Junction::BackupLocal "!insertmacro _Junction::BackupLocal"
!macro _Junction::BackupLocal _LOCALDIR _SUBDIR _PORTABLEDIR _KEY _VAR1 _VAR2
	RMDir /r "${_LOCALDIR}\${_SUBDIR}.BackupBy$AppID"
	Rename "${_LOCALDIR}\${_SUBDIR}` `${_LOCALDIR}\${_SUBDIR}.BackupBy$AppID"
	CreateDirectory "${_PORTABLEDIR}"
	CreateDirectory "${_LOCALDIR}"
	ExecDos::Exec /TOSTACK `"${J}" -accepteula -q "${_LOCALDIR}\${_SUBDIR}" "${_PORTABLEDIR}"`
	Pop ${_VAR1}
	${If} ${_VAR1} = 0
		${WriteRuntimeData} ${PAL} "${_KEY}" 1
	${Else}
		${GetFileAttributes} "${_LOCALDIR}\${_SUBDIR}" REPARSE_POINT ${_VAR1}
		${If} ${_VAR1} = 1
			${WriteRuntimeData} ${PAL} "${_KEY}" 1
		${Else}
			IfFileExists "${_PORTABLEDIR}" 0 +14
			Push "${_PORTABLEDIR}"
			Call Root
			Pop ${_VAR1}
			Push "${_LOCALDIR}"
			Call Root
			Pop ${_VAR2}
			StrCmp ${_VAR1} ${_VAR2} 0 +5
			CreateDirectory "${_LOCALDIR}"
			ClearErrors
			Rename "${_PORTABLEDIR}" "${_LOCALDIR}\${_SUBDIR}"
			IfErrors 0 +3
			CreateDirectory "${_LOCALDIR}\${_SUBDIR}"
			CopyFiles /SILENT "${_PORTABLEDIR}\*.*" "${_LOCALDIR}\${_SUBDIR}"
		${EndIf}
	${EndIf}
!macroend


!define Junction::RestoreLocal "!insertmacro _Junction::RestoreLocal"
!macro _Junction::RestoreLocal _LOCALDIR _SUBDIR _PORTABLEDIR _KEY _VAR1 _VAR2
	ClearErrors
	${ReadRuntimeData} ${_VAR1} ${PAL} "${_KEY}"
	${If} ${Errors}
		${GetFileAttributes} "${_LOCALDIR}\${_SUBDIR}" REPARSE_POINT ${_VAR1}
		${If} ${_VAR1} = 1
			ExecDos::Exec /TOSTACK `"${J}" -accepteula -d -q "${_LOCALDIR}\${_SUBDIR}"`
			Pop ${_VAR1}
			IntCmp ${_VAR1} 0 +2
			RMDir "${_LOCALDIR}\${_SUBDIR}"
		${Else}
			IfFileExists "${_LOCALDIR}\${_SUBDIR}" 0 +17
			Push "${_PORTABLEDIR}"
			Call Root
			Pop ${_VAR1}
			Push "${_LOCALDIR}"
			Call Root
			Pop ${_VAR2}
			RMDir /r "${_PORTABLEDIR}"
			RMDir "${_LOCALDIR}\${_SUBDIR}"
			IfFileExists "${_LOCALDIR}\${_SUBDIR}" 0 +7
			StrCmp ${_VAR1} ${_VAR2} 0 +4
			ClearErrors
			Rename "${_LOCALDIR}\${_SUBDIR}" "${_PORTABLEDIR}"
			IfErrors 0 +3
			CreateDirectory "${_PORTABLEDIR}"
			CopyFiles /SILENT "${_LOCALDIR}\${_SUBDIR}\*.*" "${_PORTABLEDIR}"
			RMDir "${_LOCALDIR}"
		${EndIf}
	${Else}
		ExecDos::Exec /TOSTACK `"${J}" -accepteula -d -q "${_LOCALDIR}\${_SUBDIR}"`
		Pop ${_VAR1}
		IntCmp ${_VAR1} 0 +2
		RMDir "${_LOCALDIR}\${_SUBDIR}"
	${EndIf}
	RMDir /r "${_LOCALDIR}\${_SUBDIR}"
	Rename "${_LOCALDIR}\${_SUBDIR}.BackupBy$AppID` `${_LOCALDIR}\${_SUBDIR}"
	RMDir "${_LOCALDIR}"
	RMDir "${_PORTABLEDIR}"
	RMDir "${_LOCALDIR}"
!macroend

The -q parameter is a switch to suppress any error messages when using junction.exe.

daemon.devin

John T. Haller
John T. Haller's picture
Offline
Last seen: 9 hours 5 min ago
AdminDeveloperModeratorTranslator
Joined: 2005-11-28 22:21
License Prohibits Redistribution

The license for all SysInternals products prohibits any distribution, even of the unmodified product itself without packaging it with anything else: https://docs.microsoft.com/en-us/sysinternals/license-faq

Sometimes, the impossible can become possible, if you're awesome!

demon.devin
demon.devin's picture
Offline
Last seen: 4 years 4 months ago
Developer
Joined: 2007-08-02 09:04
I therefore decided to write

I therefore decided to write my own junction-creating tool: Junction. Junction not only allows you to create NTFS junctions, it allows you to see if files or directories are actually reparse points. Reparse points are the mechanism on which NTFS junctions are based, and they are used by Windows' Remote Storage Service (RSS), as well as volume mount points.

daemon.devin

John T. Haller
John T. Haller's picture
Offline
Last seen: 9 hours 5 min ago
AdminDeveloperModeratorTranslator
Joined: 2005-11-28 22:21
License

The above quote doesn't appear to have anything to do with the license for the junction.exe tool. Or are you not redistributing it?

Sometimes, the impossible can become possible, if you're awesome!

demon.devin
demon.devin's picture
Offline
Last seen: 4 years 4 months ago
Developer
Joined: 2007-08-02 09:04
It's inside the plugins

It's inside the plugins folder inside the launcher.exe. Is that not allowed either?

daemon.devin

John T. Haller
John T. Haller's picture
Offline
Last seen: 9 hours 5 min ago
AdminDeveloperModeratorTranslator
Joined: 2005-11-28 22:21
Nope, Redistribution is totally prohibited

You can't download and give it to anyone period. You can only tell people about SysInternals tools and have them visit the website to download it themselves. If you download it and make it available yourself on your own server or in your own product, it's illegal.

Sometimes, the impossible can become possible, if you're awesome!

demon.devin
demon.devin's picture
Offline
Last seen: 4 years 4 months ago
Developer
Joined: 2007-08-02 09:04
Damn.

I assumed because he made it himself and was sharing it with the public it was okay to be using.

I'll rewrite everything accordingly.

daemon.devin

John T. Haller
John T. Haller's picture
Offline
Last seen: 9 hours 5 min ago
AdminDeveloperModeratorTranslator
Joined: 2005-11-28 22:21
Should Remove It From Any Hosting

If you're hosting it anywhere, you should pull it down ASAP as it's a copyright violation. Also, if you've hosted it on Github or SourceForge, in addition to being a copyright violation, it's a violation of the Terms of Service for being closed source.

Sometimes, the impossible can become possible, if you're awesome!

Log in or register to post comments