News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

You'd think shortcut would be quick

Started by oex, January 17, 2010, 10:02:25 AM

Previous topic - Next topic

PBrennick

oex.

Attached is a program that will create links in either or all of the following three places: desktop, shortcut menu and/or rightclick menu. I also have a program that will remove them.

Paul
The GeneSys Project is available from:
The Repository or My crappy website

donkey

Hi Paul,

Hard coding virtual folders can be problematic, you should use the API's to get the folder name for the desktop. For Vista and below use the CSIDL:

// From shlobj.h (GoAsm header project all versions)
#define CSIDL_DESKTOP 0

invoke SHGetSpecialFolderLocation, NULL, CSIDL_DESKTOP, offset PIDL
invoke SHGetPathFromIDListA,[PIDL],offset DesktopPath
invoke ILFree, [PIDL]


Note for ILFree you will have to call it by ordinal on Windows versions with Shell32 version 4.0:

// For GoAsm only:
invoke SHELL32.DLL:155, [PIDL]
// or define SHUSEORDINALS and set SHELLVER to WIN32_SHELL_40, the header project will automatically translate the call


For Win7 you should use Known Folders:

// From KnownFolders.h (GoAsm header project ver 0x020013 and above)
#DEFINE GUID_FOLDERID_Desktop <0xB4BFCC3A, 0xDB2C, 0x424C, <0xB0, 0x29, 0x7F, 0xE9, 0x9A, 0x87, 0xC6, 0x41>>

DATA SECTION
FOLDERID_Desktop GUID GUID_FOLDERID_Desktop

CODE SECTION
invoke SHGetKnownFolderPath, offset FOLDERID_Desktop, 0, NULL, offset DesktopPath

// free the path with CoTaskMemFree


Also, under UAC there may be problems writing to HKEY_CLASSES_ROOT, you are probably better off using a COM server to do the menu links. I have an example of an IContextMenu extension on my web site, I hope to get around to updating it and other examples to be UAC aware. I could be wrong about this though, it could just require a manifest or even not be an issue at all as I think HKEY_CLASSES_ROOT is virtualized anyway.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

PBrennick

Hi Edgar,

If I remember correctly, ordinal calls are a problem when using masm32.

Paul

The GeneSys Project is available from:
The Repository or My crappy website

hutch--

Paul,

Its just a notation in the DEF file but due to senile decay and having lost the example, I forget how to do it. It may show up in a Microsoft Doc somewhere so I will have a look when I get the time.

Found it. http://msdn.microsoft.com/en-us/library/hyx1zcd3(VS.71).aspx
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

Quote from: donkey on January 29, 2010, 01:50:22 AM
Hi Paul,

Hard coding virtual folders can be problematic, you should use the API's to get the folder name for the desktop. For Vista and below use the CSIDL:


I wonder if ExpandEnvironmentStrings works with all versions....

invoke ExpandEnvironmentStrings, chr$("%COMMONPROGRAMFILES%"), esi, MAX_PATH

PBrennick

Edgar,

Yes, I just noticed there is a problem when you try it with Windows 7. This is a disappointment because that means my Sudoku Installer is broken ...

Paul
The GeneSys Project is available from:
The Repository or My crappy website

donkey

Quote from: PBrennick on January 29, 2010, 05:28:57 AM
Hi Edgar,

If I remember correctly, ordinal calls are a problem when using masm32.

Paul



Hi Paul,

To call an ordinal from MASM you have to use GetProcAddress...

; Shell32.DLL is always loaded so no need for LoadLibrary
invoke GetModuleHandle, offset szShell32DllName
; Do not free the returned module handle, we did not increment the reference count
invoke GetProcAddress, eax, 155 ; using a value and not a pointer will obtain an ordinal address
mov pILFree, eax

; Because it is not possible to PROTO an ordinal call you can't use INVOKE
push PIDL
call pILFree


Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

donkey

Quote from: jj2007 on January 29, 2010, 07:35:52 AM
I wonder if ExpandEnvironmentStrings works with all versions....

invoke ExpandEnvironmentStrings, chr$("%COMMONPROGRAMFILES%"), esi, MAX_PATH

Yes, ExpandEnvironmentStrings works with all versions including Win7, however many virtual folders are not identified by environment variables, the proper method to get the folder location is using the CSIDL or Known Folders. For example I don't believe the desktop is available, the only paths I know that are guaranteed to be present are:

%WINDIR%, %USERPROFILE%, %SYSTEMROOT%, %TEMP%, %PROGRAMFILES%, %HOMEPATH%, %APPDATA% and %ALLUSERSPROFILE%

As well as a few paths to applications such as cmd.exe (%COMSPEC%) and drives (%SYSTEMDRIVE% and %HOMEDRIVE%).

So by using ExpandEnvironmentStrings you are severely limiting the allowable destinations for your app, especially since many of the ones available are virtualized or simply not allowed under UAC.

"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

donkey

Quote from: PBrennick on January 29, 2010, 01:32:27 PM
Edgar,

Yes, I just noticed there is a problem when you try it with Windows 7. This is a disappointment because that means my Sudoku Installer is broken ...

Paul


Hi Paul, try an elevation manifest in the installer, also if you name the installer setup.exe, Win7 will recognize it as an installer and will present the elevation dialog when it is run. This behavior was added specifically for legacy installers and may solve your problem by itself. I am not familiar with your sudoku app (I don't really like sudoku so I never looked at it) but if its installer has any name other than install.exe or setup.exe Windows may not recognize it as an installation program.

For the HKEY_CLASSES_ROOT problem you should really use the user classes root but if you give your installer admin privileges you may be able to write to the system root.

Elevation manifest for admin privileges (note that asInvoker is generally sufficient):

<?xml version="1.0" encoding="UTF-16" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity version="1.0.0.0"
     processorArchitecture="X86" name="AdminApp" type="win32"/>
  <description>Description of your application</description>
  <!-- Identify the application security requirements. -->
  <ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2">
    <ms_asmv2:security>
      <ms_asmv2:requestedPrivileges>
        <ms_asmv2:requestedExecutionLevel
          level="requireAdministrator"
          uiAccess="false"/>
        </ms_asmv2:requestedPrivileges>
       </ms_asmv2:security>
  </ms_asmv2:trustInfo>
</assembly>
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dedndave

hiya Edgar
i noticed a comment about not being able to INVOKE an ordinal
couldn't this method be used ? (i think it was Erol that wrote it)

.data

kernel32    db 'kernel32.dll',0
FuncName    db 'SetConsoleIcon',0
msg         db 'Click the message box to change the console icon',0
msg2        db 'Console icon changed',0
capt        db 'Test',0
func        db 0FFh,025h ; define a jump entry
            dd pFunc

.data?

hIcon       dd ?
pFunc       dd ?

SetConsoleIcon  EQU <pr1 PTR func>

.code

start:
    invoke  GetModuleHandle,0
    invoke  LoadIcon,eax,200
    mov     hIcon,eax
    invoke  GetModuleHandle,ADDR kernel32
    invoke  GetProcAddress,eax,ADDR FuncName
    mov     pFunc,eax
    invoke  MessageBox,0,ADDR msg,ADDR capt,MB_OK
    invoke  SetConsoleIcon,hIcon
    invoke  MessageBox,0,ADDR msg2,ADDR capt,MB_OK
    invoke  ExitProcess,0

END start

this example shows how to INVOKE the undocumented SetConsoleIcon function
but, i think the idea is the same

donkey

Quote from: dedndave on January 29, 2010, 05:29:19 PM
hiya Edgar
i noticed a comment about not being able to INVOKE an ordinal
couldn't this method be used ? (i think it was Erol that wrote it)...

Hi Dave,

Yeah, that looks like it works though I don't have MASM installed to try it. I was just going on memory and its been a long long time since I've used MASM. Still much easier with GoAsm since it loads the DLL at the PELoader stage but it seems to be unencumbered in MASM with that method. However, no PROTO so I wasn't too far off  :wink

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dedndave

actually, your comment was "no PROTO", to begin with Edgar, so you had it right - i just read more into it   :U
it is interesting how the <pr1 PTR funcName> works, though
it gives me some food for thought   :P

donkey

#27
Quote from: dedndave on January 29, 2010, 11:11:51 PM
actually, your comment was "no PROTO", to begin with Edgar, so you had it right - i just read more into it   :U
it is interesting how the <pr1 PTR funcName> works, though
it gives me some food for thought   :P

Some interesting stuff you can do with that, for example support multiple DLL versions in the same executable. Its a shame MASM doesn't have an UNDEF directive for prototypes though, it would make things much neater.

ILFree2  EQU <pr1 PTR func>
GetMajorVersion PROTO :DWORD

.data
Shell32 db 'Shell32.dll',0
FuncName db 'ILFree',0
func db 0FFh,025h ; define a jump entry
dd pILFree

.data?

hModule dd ?
pILFree dd ?
PIDL dd 16 DUP (?)
DesktopPath DB MAX_PATH DUP (?)

.code
start:

invoke  GetModuleHandle,ADDR Shell32
mov hModule, eax

invoke GetMajorVersion,offset Shell32

.IF eax <= 4
invoke  GetProcAddress,hModule,155
.ELSE
invoke  GetProcAddress,hModule,offset FuncName
.ENDIF
mov     pILFree,eax

invoke SHGetSpecialFolderLocation, NULL, CSIDL_DESKTOP, offset PIDL
invoke SHGetPathFromIDListA,[PIDL],offset DesktopPath
invoke ILFree2, [PIDL]

invoke  MessageBox,0,ADDR DesktopPath,NULL,MB_OK
invoke  ExitProcess,0

GetMajorVersion PROC uses ebx esi pFileName
LOCAL Verification :DWORD
LOCAL RootPath :DWORD
LOCAL pVersion :DWORD
LOCAL pVersionLen :DWORD

invoke GetFileVersionInfoSize,pFileName,ADDR Verification
mov ebx,eax
test eax,eax
jz ERROR2

invoke GlobalAlloc,040h,eax
test eax,eax
jz ERROR2
xchg ebx,eax

invoke GetFileVersionInfo,[pFileName],0,eax,ebx
test eax,eax
jz ERROR1

mov DWORD PTR RootPath,"\"
invoke VerQueryValue,ebx,ADDR RootPath,ADDR pVersion,ADDR pVersionLen
test eax,eax
jz ERROR1

mov esi,[pVersion]
mov eax,[esi+VS_FIXEDFILEINFO.dwFileVersionMS]
shr eax,16
ERROR1:
push eax
invoke GlobalFree,ebx
pop eax
ERROR2:
RET
GetMajorVersion ENDP


Actually installed MASM to test it  :bg

Edgar

EDIT - made the GetMajorVersion procedure a little more robust
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dedndave

well - that was Erol's way to do it   :bg
combining Erol and Edgar is like having a pair of aces   :U