Relaunch And Elevate, Is 64Bit OS, Is Admin, Known Folder

Share your advanced PureBasic knowledge/code with the community.
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Relaunch And Elevate, Is 64Bit OS, Is Admin, Known Folder

Post by Rescator »

This is a collection of useful procedures for Windows 5.x and later.
The elevation works on Windows XP (tested), Vista (tested), Windows 7 (tested) but should work on all Windows 5.x and 6.x.
This is the proper way to elevate besides the recommended separate executable that MicroSoft advises.
The known folder paths are those most common and which should be consistent across Windows 5.x and 6.x
The Is64BitOS should also be the proper way, and for fun it also "checks" when it is a 64bit app :P

Compile the source as an exe, with unicode (since Windows 5.x and 6.x is unicode it's no point using ascii)
Make sure to toggle the "user mode" for Vista in compiler options
.
Now start the exe and it will prompt for elevation. You can cancel or you can elevate it will handle both cases fine.
XP (all 6.x?) has a bit odd behavior depending on what you do/choose during the elevation prompt, but under "normal" elevation or cancel it behaves just like 5.x (Vista and Windows 7 etc).

PS! please pay attention to the naming of the folder flags for the GetKnownFolderPath() procedure, those are not just something I "made up" it actually is the advised general locations for where to install and app or store settings etc.
I really wanted to add Saved Games but unfortunately XP does not have a standard equivalent, it does have a My Gamed under My Documents but it's not a guaranteed path. (it could be localized for example) so that kinda sucks.

Anyway... Have fun folks making "good" apps! ;P

Code: Select all

; Copyright (c) Roger Hågensen, EmSai 2009
;	
; This software is provided 'as-is', without any express or implied
; warranty. In no event will the authors be held liable for any damages
; arising from the use of this software.
;
; Permission is granted to anyone to use this software for any purpose,
; including commercial applications, and to alter it and redistribute it
; freely, subject to the following restrictions:
;
;    1. The origin of this software must not be misrepresented; you must not
;    claim that you wrote the original software. If you use this software
;    in a product, an acknowledgment in the product documentation would be
;    appreciated but is not required.
;
;    2. Altered source versions must be plainly marked as such, and must not be
;    misrepresented as being the original software.
;
;    3. This notice may not be removed or altered from any source
;    distribution.

EnableExplicit

;Important! Under "runas" you are a different user,
;so if you wish to run a program after you have installed it,
;then make sure you do so from the exe that did the "runas",
;rather than the elvated one as that is most likely a admin user different from the current user.
;Use the optional params$ to pass along startup params and other info you want to pass along.
Procedure.i RelaunchAndElevate(params$="")
	Protected info.SHELLEXECUTEINFO,exe$
	exe$=ProgramFilename()
	If exe$
		info\hwnd            = GetForegroundWindow_()
		info\cbSize          = SizeOf(SHELLEXECUTEINFO)
		info\lpVerb          = @"runas"
		info\lpFile          = @exe$
		info\lpParameters    = @params$
		info\nShow           = #SW_SHOWNORMAL
		ProcedureReturn ShellExecuteEx_(info)
 EndIf
EndProcedure

Procedure.s GetUserName()
 Protected result$,size.i=#UNLEN
 result$=Space(size)
 If Not GetUserName_(@result$,@size)
  result$=""
 EndIf
 ProcedureReturn result$
EndProcedure

CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
	Macro Is64BitOS() ;Well duh! What ya expect, only a 64bit OS can run a 64bit app! P
	 #True
 EndMacro
CompilerElse ;Return #False if 32bit OS or if unable to determine if it's a 64bit OS!
	#PROCESSOR_ARCHITECTURE_AMD64=9
	Prototype.l IsWow64Process_(hProcess.i,*Wow64Process)
	Prototype.i GetNativeSystemInfo_(*si.SYSTEM_INFO)
	Procedure.i Is64BitOS()
	 Protected result.i=#False,dll.i,si.SYSTEM_INFO,iswow64.l=#False
		Protected GetNativeSystemInfo_.GetNativeSystemInfo_,IsWow64Process_.IsWow64Process_
		dll=OpenLibrary(#PB_Any,"kernel32.dll")
	 If dll
			IsWow64Process_=GetFunction(dll,"IsWow64Process") ;Only XP SP2+ and 2003 SP1+ has this function.
			If IsWow64Process_(GetCurrentProcess_(),@iswow64)
			 result=iswow64
			EndIf
			If Not IsWow64Process_
				GetNativeSystemInfo_=GetFunction(dll,"GetNativeSystemInfo") ;Only XP+ has this function.
				GetNativeSystemInfo_(si)
			 If si\wProcessorArchitecture=#PROCESSOR_ARCHITECTURE_AMD64
				 result=#True
				EndIf
			EndIf
	  CloseLibrary(dll)
	 EndIf
	 ProcedureReturn result
	EndProcedure
CompilerEndIf ;Return #True if it's a 64bit OS!

Prototype.l CheckTokenMembership_(TokenHandle.i,SidToCheck.i,*IsMember)
Prototype.l AllocateAndInitializeSid_(*pIdentifierAuthority,nSubAuthorityCount.b,dwSubAuthority0.l,dwSubAuthority1.l,dwSubAuthority2.l,dwSubAuthority3.l,dwSubAuthority4.l,dwSubAuthority5.l,dwSubAuthority6.l,dwSubAuthority7.l,*pSid)
Prototype.i FreeSid_(*pSid)

;Returns #True if this program/process is a member of the Administrators local group, or #False otherwise or if failure.
;Works on Windows 5.x (2000, XP, 2003, etc.) and 6.x (vista, 2008, Win7, etc.)
Procedure.i IsUserAdmin()
	Protected result.i=#True,dll.i
	Protected CheckTokenMembership_.CheckTokenMembership_,AllocateAndInitializeSid_.AllocateAndInitializeSid_,FreeSid_.FreeSid_
	Protected *AdministratorsGroup.SID_IDENTIFIER_AUTHORITY,NtAuthority.SID_IDENTIFIER_AUTHORITY

	dll=OpenLibrary(#PB_Any,"advapi32.dll")
	If dll
		CheckTokenMembership_=GetFunction(dll,"CheckTokenMembership")
		AllocateAndInitializeSid_=GetFunction(dll,"AllocateAndInitializeSid")
		FreeSid_=GetFunction(dll,"FreeSid")
		If Not (CheckTokenMembership_ Or AllocateAndInitializeSid_ Or FreeSid_)
			result=#False
		EndIf
		If result
			;NtAuthority=SECURITY_NT_AUTHORITY [0,0,0,0,0,5]
			NtAuthority\Value[0]=0
			NtAuthority\Value[1]=0
			NtAuthority\Value[2]=0
			NtAuthority\Value[3]=0
			NtAuthority\Value[4]=0
			NtAuthority\Value[5]=5
			result=AllocateAndInitializeSid_(NtAuthority,2,#SECURITY_BUILTIN_DOMAIN_RID,#DOMAIN_ALIAS_RID_ADMINS,0,0,0,0,0,0,@*AdministratorsGroup)
			If result And *AdministratorsGroup
				If Not CheckTokenMembership_(#Null,*AdministratorsGroup,@result)
					result=#False
				EndIf
				FreeSid_(*AdministratorsGroup)
			EndIf
		EndIf
		CloseLibrary(dll)
	Else
	 result=#False
	EndIf
	ProcedureReturn result
EndProcedure

#KF_FLAG_CREATE=$00008000
Prototype.i SHGetKnownFolderPath_(*rfid,dwFlags.l,hToken.i,*ppszPath)
Prototype.i SHGetFolderPath_(hwndOwner.i,nFolder.l,hToken.i,dwFlags.l,*pszPath)

;GetKnownFolderPath() will return either the current user paths or the "all users" path,
;only the most typicial folders and which are consistent in behaviour on Windows 5.x and 6.x are available.

;GetKnownFolderPath() flags, use the set the "all" argument to #True to get "all users" paths.
;For #Folder_Programs and #Folder_Appdata it is highly advised that you add a company/brand/entity sub folder,
;and within that program/app folder where you put the program files/shortcuts etc.
Enumeration 1
 #Folder_Startmenu ;The startmenu/programs path (for start menu programs icons).
 #Folder_Desktop  ;The desktop path (for desktop icons).
 #Folder_Programs  ;The advised install location for applications/programs.
 #Folder_Settings  ;The advised location for application settings/configs.
 #Folder_Documents ;Documents folder location.
EndEnumeration

;Returns #True if this program/process is a member of the Administrators local group, or #False otherwise or if failure.
Procedure.s GetKnownFolderPath(folder.i,all.i=#False) ;Windows 2000 (5.0) or later.
	Protected folder$,result.i=#True,dll.i,rfid.GUID,*path,path$,csidl.l
	Protected SHGetKnownFolderPath_.SHGetKnownFolderPath_,SHGetFolderPath_.SHGetFolderPath_

	dll=OpenLibrary(#PB_Any,"shell32.dll")
	If dll
		SHGetKnownFolderPath_=GetFunction(dll,"SHGetKnownFolderPath")
		If Not SHGetKnownFolderPath_
			result=#False
		EndIf
		If result ;Windows 6.x
		 Select folder
			 Case #Folder_Startmenu
			  If all ;FOLDERID_CommonPrograms CSIDL_COMMON_PROGRAMS {0139D44E-6AFE-49F2-8690-3DAFCAE6FFB8}
				  rfid\Data1=$0139D44E
				  rfid\Data2=$6AFE
				  rfid\Data3=$49F2
				  rfid\Data4[0]=$86
				  rfid\Data4[1]=$90
				  rfid\Data4[2]=$3D
				  rfid\Data4[3]=$AF
				  rfid\Data4[4]=$CA
				  rfid\Data4[5]=$E6
				  rfid\Data4[6]=$FF
				  rfid\Data4[7]=$B8
			  Else ;FOLDERID_Programs CSIDL_PROGRAMS {A77F5D77-2E2B-44C3-A6A2-ABA601054A51}
				  rfid\Data1=$A77F5D77
				  rfid\Data2=$2E2B
				  rfid\Data3=$44C3
				  rfid\Data4[0]=$A6
				  rfid\Data4[1]=$A2
				  rfid\Data4[2]=$AB
				  rfid\Data4[3]=$A6
				  rfid\Data4[4]=$01
				  rfid\Data4[5]=$05
				  rfid\Data4[6]=$4A
				  rfid\Data4[7]=$51
			  EndIf
			 Case #Folder_Desktop
			  If all ;FOLDERID_PublicDesktop CSIDL_COMMON_DESKTOPDIRECTORY {C4AA340D-F20F-4863-AFEF-F87EF2E6BA25}
				  rfid\Data1=$C4AA340D
				  rfid\Data2=$F20F
				  rfid\Data3=$4863
				  rfid\Data4[0]=$AF
				  rfid\Data4[1]=$EF
				  rfid\Data4[2]=$F8
				  rfid\Data4[3]=$7E
				  rfid\Data4[4]=$F2
				  rfid\Data4[5]=$E6
				  rfid\Data4[6]=$BA
				  rfid\Data4[7]=$25
			  Else ;FOLDERID_Desktop CSIDL_DESKTOP {B4BFCC3A-DB2C-424C-B029-7FE99A87C641}
				  rfid\Data1=$B4BFCC3A
				  rfid\Data2=$DB2C
				  rfid\Data3=$424C
				  rfid\Data4[0]=$B0
				  rfid\Data4[1]=$29
				  rfid\Data4[2]=$7F
				  rfid\Data4[3]=$E9
				  rfid\Data4[4]=$9A
				  rfid\Data4[5]=$87
				  rfid\Data4[6]=$C6
				  rfid\Data4[7]=$41
			  EndIf
			 Case #Folder_Programs
			  If all ;FOLDERID_ProgramFiles CSIDL_PROGRAM_FILES {905e63b6-c1bf-494e-b29c-65b732d3d21a}
				  rfid\Data1=$905E63B6
				  rfid\Data2=$C1BF
				  rfid\Data3=$494E
				  rfid\Data4[0]=$B2
				  rfid\Data4[1]=$9C
				  rfid\Data4[2]=$65
				  rfid\Data4[3]=$B7
				  rfid\Data4[4]=$32
				  rfid\Data4[5]=$D3
				  rfid\Data4[6]=$D2
				  rfid\Data4[7]=$1A
			  Else ;FOLDERID_LocalAppData CSIDL_LOCAL_APPDATA {F1B32785-6FBA-4FCF-9D55-7B8E7F157091}
				  rfid\Data1=$F1B32785
				  rfid\Data2=$6FBA
				  rfid\Data3=$4FCF
				  rfid\Data4[0]=$9D
				  rfid\Data4[1]=$55
				  rfid\Data4[2]=$7B
				  rfid\Data4[3]=$8E
				  rfid\Data4[4]=$7F
				  rfid\Data4[5]=$15
				  rfid\Data4[6]=$70
				  rfid\Data4[7]=$91
			  EndIf
			 Case #Folder_Settings
			  If all ;FOLDERID_ProgramData CSIDL_COMMON_APPDATA 	{62AB5D82-FDC1-4DC3-A9DD-070D1D495D97}
				  rfid\Data1=$62AB5D82
				  rfid\Data2=$FDC1
				  rfid\Data3=$4DC3
				  rfid\Data4[0]=$A9
				  rfid\Data4[1]=$DD
				  rfid\Data4[2]=$07
				  rfid\Data4[3]=$0D
				  rfid\Data4[4]=$1D
				  rfid\Data4[5]=$49
				  rfid\Data4[6]=$5D
				  rfid\Data4[7]=$97
			  Else ;FOLDERID_RoamingAppData CSIDL_APPDATA {3EB685DB-65F9-4CF6-A03A-E3EF65729F3D}
				  rfid\Data1=$3EB685DB
				  rfid\Data2=$65F9
				  rfid\Data3=$4CF6
				  rfid\Data4[0]=$A0
				  rfid\Data4[1]=$3A
				  rfid\Data4[2]=$E3
				  rfid\Data4[3]=$EF
				  rfid\Data4[4]=$65
				  rfid\Data4[5]=$72
				  rfid\Data4[6]=$9F
				  rfid\Data4[7]=$3D
			  EndIf
			 Case #Folder_Documents
			  If all  ;FOLDERID_PublicDocuments CSIDL_COMMON_DOCUMENTS {ED4824AF-DCE4-45A8-81E2-FC7965083634}
				  rfid\Data1=$ED4824AF
				  rfid\Data2=$DCE4
				  rfid\Data3=$45A8
				  rfid\Data4[0]=$81
				  rfid\Data4[1]=$E2
				  rfid\Data4[2]=$FC
				  rfid\Data4[3]=$79
				  rfid\Data4[4]=$65
				  rfid\Data4[5]=$08
				  rfid\Data4[6]=$36
				  rfid\Data4[7]=$34
			  Else ;FOLDERID_Documents #CSIDL_PERSONAL {FDD39AD0-238F-46AF-ADB4-6C85480369C7}
				  rfid\Data1=$FDD39AD0
				  rfid\Data2=$238F
				  rfid\Data3=$46AF
				  rfid\Data4[0]=$AD
				  rfid\Data4[1]=$B4
				  rfid\Data4[2]=$6C
				  rfid\Data4[3]=$85
				  rfid\Data4[4]=$48
				  rfid\Data4[5]=$03
				  rfid\Data4[6]=$69
				  rfid\Data4[7]=$C7
			  EndIf
			 Default
			  result=#False
		 EndSelect
		 If result
 			result=SHGetKnownFolderPath_(rfid,#KF_FLAG_CREATE,#Null,@*path)
	 		If (result=#S_OK) And *path
	 		 folder$=PeekS(*path)
		 	EndIf
		 	If *path
		 	 CoTaskMemFree_(*path)
		 	EndIf
	 	EndIf
		Else ;Legacy (Windows 5.x)
			SHGetFolderPath_=GetFunction(dll,"SHGetFolderPathW")
			If SHGetFolderPath_
				result=#True
			EndIf
			If result
			 Select folder
				 Case #Folder_Startmenu
				  If all
 				  csidl=#CSIDL_COMMON_PROGRAMS
				  Else
 				  csidl=#CSIDL_PROGRAMS
				  EndIf
				 Case #Folder_Desktop
				  If all
 				  csidl=#CSIDL_COMMON_DESKTOPDIRECTORY
				  Else
					  csidl=#CSIDL_DESKTOP
				  EndIf
				 Case #Folder_Programs
				  If all
 				  csidl=#CSIDL_PROGRAM_FILES
				  Else
					  csidl=#CSIDL_LOCAL_APPDATA 
				  EndIf
				 Case #Folder_Settings
				  If all
 				  csidl=#CSIDL_COMMON_APPDATA
				  Else
					  csidl=#CSIDL_APPDATA
				  EndIf
				 Case #Folder_Documents
				  If all
					  csidl=#CSIDL_COMMON_DOCUMENTS
				  Else
 				  csidl=#CSIDL_PERSONAL
				  EndIf
				 Default
				  result=#False
			 EndSelect
			 If result
			  path$=Space(#MAX_PATH)
     If SHGetFolderPath_(#Null,csidl,#Null,#SHGFP_TYPE_CURRENT,@path$)=#S_OK
		 		 folder$=Trim(path$)
					EndIf
		 	EndIf
			EndIf
		EndIf
	 If Len(folder$)
		 If Not (Right(folder$,1)="\")
		  folder$+"\"
		 EndIf
	 EndIf
		CloseLibrary(dll)
	EndIf
	ProcedureReturn folder$
EndProcedure

;Example

If Not IsUserAdmin()
 MessageRequester("Example instructions:","You can cancel the elevation and this example will actually handle this."+#LF$+#LF$+"The user will vary depending on the elevation."+#LF$+#LF$+"It's advised to open a window/msgbox before trying the elevation,"+#LF$+"otherwise a canceled/failed elevation may cause the program to open behind other windows,"+#LF$+"XP still has issues with this.")
 If RelaunchAndElevate()
  End
 Else
  MessageRequester("Elevation status:","We are not elevated (failed or canceled)!")
 EndIf
Else
 MessageRequester("Elevation status:","We are elevated!")
EndIf

Define text$

text$+"Is64BitOS="+Str(Is64BitOS())+#LF$
text$+"IsUserAdmin="+Str(IsUserAdmin())+#LF$
text$+""+#LF$
text$+"Current User="+GetUserName()+#LF$+#LF$
text$+"Startmenu="+GetKnownFolderPath(#Folder_Startmenu,#False)+"YourCompany\YourApp\"+#LF$
text$+"Desktop="+GetKnownFolderPath(#Folder_Desktop,#False)+#LF$
text$+"Programs="+GetKnownFolderPath(#Folder_Programs,#False)+"YourCompany\YourApp\"+#LF$
text$+"Settings="+GetKnownFolderPath(#Folder_Settings,#False)+"YourCompany\YourApp\"+#LF$
text$+"Documents="+GetKnownFolderPath(#Folder_Documents,#False)+#LF$
text$+""+#LF$
text$+"All Users"+#LF$
text$+"Startmenu="+GetKnownFolderPath(#Folder_Startmenu,#True)+"YourCompany\YourApp\"+#LF$
text$+"Desktop="+GetKnownFolderPath(#Folder_Desktop,#True)+#LF$
text$+"Programs="+GetKnownFolderPath(#Folder_Programs,#True)+"YourCompany\YourApp\"+#LF$
text$+"Settings="+GetKnownFolderPath(#Folder_Settings,#True)+"YourCompany\YourApp\"+#LF$
text$+"Documents="+GetKnownFolderPath(#Folder_Documents,#True)+#LF$
MessageRequester("Paths",text$)
Last edited by Rescator on Sat Jan 02, 2010 3:00 pm, edited 2 times in total.
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Re: Relaunch And Activate, Is 64Bit OS, Is Admin, Known Folder

Post by Inf0Byt3 »

Very nice work man! These will come in very handy :D.
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
User avatar
luis
Addict
Addict
Posts: 3876
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Relaunch And Activate, Is 64Bit OS, Is Admin, Known Folder

Post by luis »

Thank you :)
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: Relaunch And Activate, Is 64Bit OS, Is Admin, Known Folder

Post by ts-soft »

Paths wrote:---------------------------
Paths
---------------------------
Is64BitOS=1
IsUserAdmin=1

Current User=Thomas

Startmenu=C\YourCompany\YourApp\
Desktop=C\
Programs=C\YourCompany\YourApp\
Settings=C\YourCompany\YourApp\
Documents=C\

All Users
Startmenu=C\YourCompany\YourApp\
Desktop=C\
Programs=C\YourCompany\YourApp\
Settings=C\YourCompany\YourApp\
Documents=C\

---------------------------
OK
---------------------------
I think that is not the right result?
Tested with PB 4.40 x86 and x64 in windows seven
Tested with PB 4.40 x86 in windows xp
with always the same result.

greetings
Thomas
moogle
Enthusiast
Enthusiast
Posts: 372
Joined: Tue Feb 14, 2006 9:27 pm
Location: London, UK

Re: Relaunch And Activate, Is 64Bit OS, Is Admin, Known Folder

Post by moogle »

ts-soft wrote: I think that is not the right result?
Tested with PB 4.40 x86 and x64 in windows seven
Tested with PB 4.40 x86 in windows xp
with always the same result.

greetings
Thomas
Same results here, everything is right except the KnownPaths :)

-Vista x64
Image
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Re: Relaunch And Activate, Is 64Bit OS, Is Admin, Known Folder

Post by SFSxOI »

After experiencing the same issue as the two above, I read the original post again. :) Compile as unicode and it works fine here now on Windows 7 Ultimate 32 bit. :)
Last edited by SFSxOI on Fri Jan 01, 2010 9:12 pm, edited 1 time in total.
The advantage of a 64 bit operating system over a 32 bit operating system comes down to only being twice the headache.
moogle
Enthusiast
Enthusiast
Posts: 372
Joined: Tue Feb 14, 2006 9:27 pm
Location: London, UK

Re: Relaunch And Activate, Is 64Bit OS, Is Admin, Known Folder

Post by moogle »

SFSxOI wrote:compile as unicode and it works. :)
whoops! :lol:
Image
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: Relaunch And Activate, Is 64Bit OS, Is Admin, Known Folder

Post by ts-soft »

SFSxOI wrote:After experiencing the same issue as the two above, I read the original post again. :) Compile as unicode and it works fine here now on Windows 7 Ultimate 32 bit. :)
:oops:
this make sense.

Works fine here after changing to unicode :D
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Re: Relaunch And Activate, Is 64Bit OS, Is Admin, Known Folder

Post by Rescator »

Bolded the two lines stating how to compile :P

PS! SHGetKnownFolderPath is unicode (aka w or wide) a lot of features introduced from Win2000 and onwards are that, so it's easy to get messed up text unless you pay attention to what the MSDN/SDK says.
And some may have noticed that i use SHGetFolderPathW rather than SHGetFolderPath_(), reason for this is that SHGetKnownFolderPath is the replacement for SHGetFolderPath so no point requiring both, this way the code will work if say Windows 8 removes SHGetFolderPath (not very likely heh)
SHGetFolderPath is a wrapper for SHGetKnownFolderPath from vista onwards, so calling SHGetKnownFolderPath is less overhead in that respect. *shrug*
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Re: Relaunch And Elevate, Is 64Bit OS, Is Admin, Known Folde

Post by Fluid Byte »

Just needed this to create a multi EXE launcher (32Bit/64Bit).

Good stuff!
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
whizza
User
User
Posts: 46
Joined: Tue Nov 13, 2007 4:41 pm
Location: England

Re: Relaunch And Elevate, Is 64Bit OS, Is Admin, Known Folde

Post by whizza »

Very educational. Thank your for sharing.
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Relaunch And Elevate, Is 64Bit OS, Is Admin, Known Folde

Post by IdeasVacuum »

Very useful, MSDN info so confusing!

However, not sure that the alternative to FOLDERID_ProgramFiles should be FOLDERID_LocalAppData, two different things there.

Edit: Looks as though you can pass the GUId (rfid.GUID) as a special string:
http://vbnet.mvps.org/index.html?code/b ... erpath.htm

.........which is a lot easier/tidier given that there is in fact a huge list of known folders
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Re: Relaunch And Elevate, Is 64Bit OS, Is Admin, Known Folde

Post by Rescator »

IdeasVacuum wrote:Very useful, MSDN info so confusing!
Yep! At times it might even seem contradicting.
IdeasVacuum wrote:However, not sure that the alternative to FOLDERID_ProgramFiles should be FOLDERID_LocalAppData, two different things there.
Actually for system/all users installation FOLDERID_ProgramFiles is correct, and for current user only install (no admin access needed) FOLDERID_LocalAppData is correct. This is not something I came up with, but is actually the path recommendation by Microsoft and has been such for years now. Just look in C:\Users\USERNAME\AppData\Local

IdeasVacuum wrote:Edit: Looks as though you can pass the GUId (rfid.GUID) as a special string:
http://vbnet.mvps.org/index.html?code/b ... erpath.htm

.........which is a lot easier/tidier given that there is in fact a huge list of known folders
No idea why you are referring to visual basic .net code, also in PureBasic there is no such special string.
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Relaunch And Elevate, Is 64Bit OS, Is Admin, Known Folde

Post by IdeasVacuum »

MSDN:
The file system directory that serves as a data repository
That's the app's data, not the executable itself.

The GUID string is made "special" by enclosing it in curly brackets:
#FOLDERID_ProgramFilesX86 = "{7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E}"
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Re: Relaunch And Elevate, Is 64Bit OS, Is Admin, Known Folde

Post by Rescator »

IdeasVacuum wrote:The GUID string is made "special" by enclosing it in curly brackets:
#FOLDERID_ProgramFilesX86 = "{7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E}"
That's a normal PureBasic constant string.

You are missing the part where that visual basic example uses the Win32 API function CLSIDFromString() to turn a normal string to rfid structure. (or more precisely populates a pre allocated memory the size of a .rfid structure.
Please check the facts or provide PureBasic code that shows PureBasic using "special" GUID strings.
You are confusing PureBasic beginners with statements like that.
IdeasVacuum wrote:MSDN:
The file system directory that serves as a data repository
That's the app's data, not the executable itself.
Please see http://msdn.microsoft.com/en-us/library/dd765197.aspx
Windows Server 2008 R2 and Windows 7: The property value is the full path of the Programs folder for the current user (for example, %LocalAppData%\Programs.) The identifier for this folder is FOLDERID_UserProgramFiles on 32-bit and 64-bit systems. There is no equivalent CSIDL identifier for FOLDERID_UserProgramFiles. Files in this folder can be accessed only by the user that installed this folder.

Windows Server 2008 and earlier, and Windows Vista and earlier: No per-user capable folder is available
Both Google Chrome and MicroSoft Skydrive installs (per user install) under %LocalAppData%
Ideally it would be "%LocalAppData%\Programs" but that made SHGetKnownFolderPath fail when retrieving FOLDERID_UserProgramFiles, ad sure enough on my Windows 7 machine there is no "%LocalAppData%\Programs" folder, creating the folder manually though and SHGetKnownFolderPath returns "C:\Users\USERNAME\AppData\Local\Programs"
Why the Google Chrome and MicroSoft Skydrive installs do not use the KF_FLAG_CREATE with SHGetKnownFolderPath I can only speculate as the description is the following:
KF_FLAG_CREATE
0x00008000. Forces the creation of the specified folder if that folder does not already exist. The security provisions predefined for that folder are applied. If the folder does not exist and cannot be created, the function returns a failure code and no path is returned.
And the folder may or may not be accessible/created at all.
At least %LocalAppData% is guaranteed (somewhat) to be available.

We'll see what MicroSoft does in Windows 9 to try and rectify this, maybe a %LocalPrograms" pointing to "C:\Users\USERNAME\AppData\LocalPrograms\". *shrug*
Then again a .exe is also program data (in fact many exe's has icons and audio and much more stored within it so in that regard is no different than a data archive when using LoadResource and similar. So "%LocalAppData%" is no more odd than "%LocalAppData%\Programs", and at least %LocalAppData% exist from Windows 2000 (Windows 5.0) and up to Windows 8 (Windows 6.2)

Also, a per user install need not be restricted to %LocalAppData% (or %LocalAppData%\Programs if that actually worked on all systems), any location that the current user can write to is acceptable.
But the benefit of %LocalAppData%\Programs (at least under Vista and later) is that it is only accessible to the current user (and admins).
That way a Wife need not find out that a Husband has installed a virtual girlfriend program for example. (although the access permissions on my system seems to be messed up so that feature does not seem to work.)
%LocalAppData% is a good default for per user installs (certainly better than %ProgramFiles% (FOLDERID_ProgramFiles) that needs elevation and is intended for all users installs).

Now if you still wish to argue about this then please take it to the Windows Installer Team at MicroSoft, the link above points to the official documentation for Windows Installer and if anyone "wrote the book" on installations it's the Windows Installer Team.
Post Reply