April 26, 2024, 04:51:41 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Is this a bug or am I doing something wrong?

Started by Parker, December 16, 2005, 10:11:19 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Parker

I'm trying to convert the shortcut example from IB to aurora. I have the following:
/*
COM example program. Creates a shortcut on the desktop
Compile as CONSOLE target. After running a shortcut
to this executable wll be created on your desktop.
Delete the shortcut when finshed.
*/

//include the file defining the COM interfaces we use
#typedef UINT unsigned int
#typedef CHAR unsigned byte
struct GUID,1
{
DEF data1 as UINT;
DEF data2 as WORD;
DEF data3 as WORD;
DEF data4[8] as CHAR;
}
DECLARE IMPORT,CoInitialize(lpvoid as POINTER),INT;
DECLARE IMPORT,CoUninitialize();
DECLARE IMPORT,CoCreateInstance(rclsid as GUID,pUnkOuter as POINTER,dwClsContext as UINT,riid as GUID,ppv as POINTER),INT;
#use "uuid.lib"
#use "ole32.lib"
#use "shell32.lib"

#include "ishelllink.inc"

//A few necessary constants
CONST CP_ACP = 0;
CONST CLSCTX_INPROC_SERVER = 1;
DECLARE IMPORT,MultiByteToWideChar(codepage as UINT,dwFlags as UINT,lpMBS as STRING,cchMB as INT,lpWCS as POINTER,cchWC as INT);
//MAX_PATH = 260
DEF desktopPath[260] as DSTRING;
DEF objectPath[260] as DSTRING;
DEF description as STRING;

global sub main()
{
//Just in case we are compiled for a Windows target
OPENCONSOLE();
//Make sure COM is active
CoInitialize(NULL);
//Get the desktop folder path
desktopPath = GetFolderLocation(0);
//the .lnk file
desktopPath += "\\shell_COM_example.lnk";
//What we are linking to..namely this executable.
objectPath = GETSTARTPATH() + "shell_COM_example.exe";
//The description
description = "shell_COM_example";
//Create the link
IF CreateLink(objectPath,desktopPath,description) = 0
writeln( "Shortcut created OK!" )
ELSE
writeln( "Unable to create shortcut\n")
;
//Shut down COM
CoUninitialize();
writeln( "Press any key to close\n" );
WHILE GetKey()="";

return;
}

/*
the subroutine that does the real work and creates the desktop shortcut using COM
embellish as needed to include other shortcut parameters such as the
working directory and program arguments:
psl->SetWorkingDirectory(path)
psl->SetArguments(args)
*/

SUB CreateLink(lpszPathObj as STRING,lpszPathLink as STRING,lpszDesc as STRING),INT
{
    INT hres;hres = 0;
    IShellLinkA *psl;
IPersistFile *ppf;
    //Get a pointer to the IShellLink interface.
    hres = CoCreateInstance(_CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, _IID_IShellLinkA, psl);
    if (hres = 0)
{
writeln( "IShellLinkA object created\n" );
        //Set the path to the shortcut target, and add the
        //description.
        *psl.SetPath(lpszPathObj);
        *psl.SetDescription(lpszDesc);

       //Query IShellLink for the IPersistFile interface for saving the
       //shortcut in persistent storage.
        hres = *psl.QueryInterface(_IID_IPersistFile,ppf);
if (hres = 0)
{
writeln( "IPersistFile object obtained\n" );
            WORD wsz[260];
             //Ensure that the string is ANSI unicode.
            MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1,wsz, 260);
             //Save the link by calling IPersistFile->Save.
            hres = *ppf.Save(wsz, TRUE);
            *ppf.Release();
        }
        *psl.Release();
    }
    return hres;
}

/* just a function that might be useful to you. Gets the current users special folder locations
such as the desktop path or windows path, etc.
Not every ID will resolve to a folder on all systems
USEAGE:
path = GetFolderLocation(ID)
Where ID is one of: */

CONST CSIDLDESKTOP = 0x0000;
CONST CSIDLPROGRAMS = 0x0002;
CONST CSIDLCONTROLS = 0x0003;
CONST CSIDLPRINTERS = 0x0004;
CONST CSIDLPERSONAL = 0x0005;
CONST CSIDLFAVORITES = 0x0006;
CONST CSIDLSTARTUP = 0x0007;
CONST CSIDLRECENT = 0x0008;
CONST CSIDLSENDTO = 0x0009;
CONST CSIDLBITBUCKET = 0x000a;
CONST CSIDLSTARTMENU = 0x000b;
CONST CSIDLDESKTOPDIRECTORY = 0x0010;
CONST CSIDLDRIVES = 0x0011;
CONST CSIDLNETWORK = 0x0012;
CONST CSIDLNETHOOD = 0x0013;
CONST CSIDLFONTS = 0x0014;
CONST CSIDLTEMPLATES = 0x0015;
CONST CSIDLCMNSTARTMENU = 0x0016;
CONST CSIDLCMNPROGRAMS = 0x0017;
CONST CSIDLCMNSTARTUP = 0x0018;
CONST CSIDLCMNDESKTOPDIRECTORY = 0x0019;
CONST CSIDLAPPDATA = 0x001a;
CONST CSIDLPRINTHOOD = 0x001b;

DECLARE IMPORT,SHGetSpecialFolderLocation(hwnd as UINT,nFolder as INT,ppITEMIDLIST as POINTER),int;
DECLARE IMPORT,SHGetPathFromIDList(pITEMIDLIST as POINTER,PATH as STRING),int;
DECLARE IMPORT,CoTaskMemFree(pidl as POINTER);

SUB GetFolderLocation(nFolder as INT),STRING
{
     DEF path[260] as DSTRING;
     DEF pidl as POINTER;
     DEF ppidl as POINTER;
     ppidl = &pidl;
     SHGetSpecialFolderLocation(NULL,nFolder,ppidl);
     SHGetPathFromIDList(pidl,path);
     CoTaskMemFree(pidl);
RETURN path;
}


ishelllink.inc
/*sample from the users guide. Defining a COM object interface
for the Windows IShellLink object. This is a partial conversion
of the windows include file SHLOBJ.H*/

/*IBasic Pro links with UUID.LIB so the GUID's of most
system objects are available,usually with an underscore */
EXTERN _CLSID_ShellLink as GUID;
EXTERN _IID_IShellLinkA as GUID;
EXTERN _IID_IPersistFile as GUID;
/*
// SHITEMID -- Item ID from SHLOBJ.H
*/
struct SHITEMID // mkid
{
WORD cb; // Size of the ID (including cb itself)
BYTE abID[1]; // The item ID (variable length)
}


/*
// ITEMIDLIST -- List if item IDs (combined with 0-terminator)
*/
struct ITEMIDLIST     
{
SHITEMID mkid;
}

/* FILETIME and WIN32_FIND_DATAA from WINBASE.H */

struct FILETIME
{
    DEF dwLowDateTime as UINT;
    DEF dwHighDateTime as UINT;
}

struct WIN32_FIND_DATAA
{
    DEF dwFileAttributes as UINT;
    DEF ftCreationTime as FILETIME;
    DEF ftLastAccessTime as FILETIME;
    DEF ftLastWriteTime as FILETIME;
    DEF nFileSizeHigh as UINT;
    DEF nFileSizeLow as UINT;
    DEF dwReserved0 as UINT;
    DEF dwReserved1 as UINT;
    DEF cFileName[ 260 ] as CHAR;
    DEF cAlternateFileName[ 14 ] as CHAR;
}

//The interface description for IShellLink
class IUnknown
{
declare virtual QueryInterface(riid as POINTER, ppvObj as POINTER),UINT;
declare virtual AddRef(),UINT;
declare virtual Release(),UINT;
}

class IShellLinkA : IUnknown
{
declare virtual GetPath(pszFile as STRING,cchMaxPath as INT, pdf as WIN32_FIND_DATAA,fFlags as UINT);
declare virtual GetIDList(ppidl as POINTER);
declare virtual SetIDList(ppidl as ITEMIDLIST);
declare virtual GetDescription(pszName as STRING,cchMaxName as INT);
declare virtual SetDescription(pszName as STRING);
declare virtual GetWorkingDirectory(pszDir as STRING,cchMaxPath as INT);
declare virtual SetWorkingDirectory(pszDir as STRING);
declare virtual GetArguments(pszArgs as STRING,cchMaxPath as INT);
declare virtual SetArguments(pszArgs as STRING);
declare virtual GetHotkey(pwHotkey as WORD BYREF);
declare virtual SetHotkey(wHotkey as WORD);
declare virtual GetShowCmd(piShowCmd as INT BYREF);
declare virtual SetShowCmd(iShowCmd as INT);
declare virtual GetIconLocation(pszIconPath as STRING,cchIconPath as INT,piIcon as INT BYREF);
declare virtual SetIconLocation(pszIconPath as STRING,iIcon as INT);
declare virtual SetRelativePath(pszPathRel as STRING,dwReserved as UINT);
declare virtual Resolve(hwnd as UINT,fFlags as UINT);
declare virtual SetPath(pszFile as STRING);
}

//The interface description for IPersistFile

class IPersistFile : IUnknown
{
declare virtual GetClassID(/* [out] */pClassID as POINTER),UINT;
declare virtual IsDirty(),UINT;
declare virtual Load(/* [in] unicode */pszFileName as POINTER, /* [in] */dwMode as UINT),UINT;
declare virtual Save(/* [unique][in] unicode*/pszFileName as POINTER,/* [in] */fRemember as INT),UINT;
declare virtual SaveCompleted(/* [unique][in] unicode */pszFileName as POINTER),UINT;
declare virtual GetCurFile(/* [out] */ppszFileName as POINTER),UINT;
}


I get the following output:
Compiling...
shortcut.src
C:\dev\ac\shortcut.src:151: error: symbol `IUnknown@QueryInterface' undefined
C:\dev\ac\shortcut.src:151: error: symbol `IUnknown@AddRef' undefined
C:\dev\ac\shortcut.src:151: error: symbol `IUnknown@Release' undefined
C:\dev\ac\shortcut.src:151: error: symbol `IUnknown@QueryInterface' undefined
C:\dev\ac\shortcut.src:151: error: symbol `IUnknown@AddRef' undefined
C:\dev\ac\shortcut.src:151: error: symbol `IUnknown@Release' undefined
C:\dev\ac\shortcut.src:151: error: phase error detected at end of assembly.
Error(s) in assembling C:\dev\ac\shortcut.asm


I declared them as virtual and used pointers to the class, I don't know what's wrong.

Zen

Post the shortcut.src so we can have a look. Im no COM guy but somethimes its just silly little things that you dont notice yourself.

Lewis

Parker


Zen

Sorry parker. I just glanced at it and saw mostly IBasic keywords. Ill have a look now.

Lewis

Parker

That's because it's a direct translation of the IB one. I didn't add all that much except semicolons, a couple typedefs, type->struct.

Zen

Hmm well i dont have a clue. But it was worth a try. It doesnt seem to be anything too obvious anyway. Paul did say that Aurora doesnt officialy support COM yet so it may have a few glitches here and there.

Sorry about that
Lewis

Parker

Okay, I figured it out. It's a compiler bug. Apparently when you call inherited methods they don't get declared correctly and NASM gives errors. Not that they actually exist, they just get overwritten by COM, but NASM minds.

Zen

Cool. How did you manage to find that out then? Sometimes i think your too clever. lol

Lewis

Parker

I looked in the assembly code. Search for IUnknown@Release. You won't find any extern definition. But for the methods that are called directly as part of that class, you'll find one, which causes NASM to not generate an error.

Edit: Oops, forgot to post the asm.

segment .text use32 align=16
extern _astrcpy
extern _astrlen
extern _astrcat
extern _i64mul
extern _i64div
extern _ui64div
extern _i64rem
extern _ui64rem
extern _sys_double
extern _CLSID_ShellLink
extern _IID_IShellLinkA
extern _IID_IPersistFile
global main
extern GETKEY
extern IPersistFile@SaveCompleted
extern __imp_CoTaskMemFree
extern IShellLinkA@GetShowCmd
extern IShellLinkA@GetArguments
extern __imp_CoCreateInstance
extern IShellLinkA@GetHotkey
extern OPENCONSOLE
extern IShellLinkA@GetIconLocation
extern IShellLinkA@GetWorkingDirectory
extern IShellLinkA@SetPath
extern __imp_SHGetSpecialFolderLocation
extern IPersistFile@IsDirty
extern __imp_CoInitialize
extern IShellLinkA@Resolve
extern _dupstr
extern __imp_CoUninitialize
extern IShellLinkA@GetIDList
extern IShellLinkA@SetArguments
extern HeapClear
extern WRITELN
extern __imp_lstrcmpA
extern IShellLinkA@SetDescription
extern IShellLinkA@SetIconLocation
extern FreeHeap
extern IShellLinkA@GetPath
extern IPersistFile@Load
extern __imp_SHGetPathFromIDList
extern IPersistFile@GetClassID
extern IPersistFile@Save
extern IShellLinkA@SetShowCmd
extern IShellLinkA@SetHotkey
extern GETSTARTPATH
extern IPersistFile@GetCurFile
extern PushHeap
extern _strappend
extern IShellLinkA@SetRelativePath
extern IShellLinkA@GetDescription
extern IShellLinkA@SetWorkingDirectory
extern AllocHeap
extern __imp_MultiByteToWideChar
extern IShellLinkA@SetIDList
%define _@@main_ 0
%define _@@CreateLink_ 532
%define _@@GetFolderLocation_ 268
%line 10+0 C:\dev\ac\shortcut.src
%line 11+0 C:\dev\ac\shortcut.src
%line 18+0 C:\dev\ac\shortcut.src
%line 18+0 C:\dev\ac\shortcut.src
%line 19+0 C:\dev\ac\shortcut.src
%line 20+0 C:\dev\ac\shortcut.src
%line 21+0 C:\dev\ac\shortcut.src
%line 22+0 C:\dev\ac\shortcut.src
%line 23+0 C:\dev\ac\shortcut.src
%line 7+0 ishelllink.inc
%line 8+0 ishelllink.inc
%line 9+0 ishelllink.inc
%line 18+0 ishelllink.inc
%line 27+0 ishelllink.inc
%line 35+0 ishelllink.inc
%line 49+0 ishelllink.inc
%line 52+0 ishelllink.inc
%line 53+0 ishelllink.inc
%line 54+0 ishelllink.inc
%line 55+0 ishelllink.inc
%line 57+0 ishelllink.inc
%line 59+0 ishelllink.inc
%line 60+0 ishelllink.inc
%line 61+0 ishelllink.inc
%line 62+0 ishelllink.inc
%line 63+0 ishelllink.inc
%line 64+0 ishelllink.inc
%line 65+0 ishelllink.inc
%line 66+0 ishelllink.inc
%line 67+0 ishelllink.inc
%line 68+0 ishelllink.inc
%line 69+0 ishelllink.inc
%line 70+0 ishelllink.inc
%line 71+0 ishelllink.inc
%line 72+0 ishelllink.inc
%line 73+0 ishelllink.inc
%line 74+0 ishelllink.inc
%line 75+0 ishelllink.inc
%line 76+0 ishelllink.inc
%line 77+0 ishelllink.inc
%line 79+0 ishelllink.inc
%line 83+0 ishelllink.inc
%line 84+0 ishelllink.inc
%line 85+0 ishelllink.inc
%line 86+0 ishelllink.inc
%line 87+0 ishelllink.inc
%line 88+0 ishelllink.inc
%line 89+0 ishelllink.inc
%line 91+0 ishelllink.inc
%line 28+0 C:\dev\ac\shortcut.src
%line 29+0 C:\dev\ac\shortcut.src
%line 30+0 C:\dev\ac\shortcut.src
%line 32+0 C:\dev\ac\shortcut.src
%line 33+0 C:\dev\ac\shortcut.src
%line 34+0 C:\dev\ac\shortcut.src
;subroutine main begin
$main:
.bf
push ebp
mov ebp,esp
sub esp,_@@main_
push ebx
push edi
push esi
%line 37+0 C:\dev\ac\shortcut.src
%line 39+0 C:\dev\ac\shortcut.src
call $OPENCONSOLE
%line 41+0 C:\dev\ac\shortcut.src
mov eax,0
mov edx,eax
push edx
call [__imp_CoInitialize]
%line 43+0 C:\dev\ac\shortcut.src
mov eax, $desktopPath
push eax
xor eax,eax
push eax
call $GetFolderLocation
mov edx,eax
pop esi
push edx
push edx
push esi
call _astrcpy
call FreeHeap
%line 45+0 C:\dev\ac\shortcut.src
mov eax, $desktopPath
push eax
mov eax,STR00000
mov esi,eax
push esi
call _dupstr
mov edi,eax
push edi
mov eax, $desktopPath
mov esi,eax
pop edi
push edi
push esi
call _strappend
add esp,8
push eax
push edi
call FreeHeap
pop edx
mov eax,edx
mov edx,eax
pop esi
push edx
push edx
push esi
call _astrcpy
call FreeHeap
%line 47+0 C:\dev\ac\shortcut.src
mov eax, $objectPath
push eax
mov eax,STR00001
mov esi,eax
push esi
call _dupstr
mov edi,eax
push edi
call $GETSTARTPATH
mov esi,eax
pop edi
push edi
push esi
call _strappend
add esp,8
push eax
push esi
call FreeHeap
push edi
call FreeHeap
pop edx
mov eax,edx
mov edx,eax
pop esi
push edx
push edx
push esi
call _astrcpy
call FreeHeap
%line 49+0 C:\dev\ac\shortcut.src
mov eax, $description
push eax
mov eax,STR00002
mov edx,eax
pop esi
push edx
push esi
call _astrcpy
%line 55+0 C:\dev\ac\shortcut.src
xor eax,eax
push eax
mov ebx, $description
mov edx,ebx
push edx
mov ebx, $desktopPath
mov edx,ebx
push edx
mov ebx, $objectPath
mov edx,ebx
push edx
call $CreateLink
mov esi,eax
pop eax
mov ebx,esi
mov esi,ebx
mov edi,eax
cmp esi,edi
sete dl
and edx,dword 0x000000ff
mov eax,edx
test eax,eax
jz near dword L00000
mov eax,STR00003
mov edx,eax
push edx
call $WRITELN
jmp L00001
L00000:
mov eax,STR00004
mov edx,eax
push edx
call $WRITELN
L00001:
%line 57+0 C:\dev\ac\shortcut.src
call [__imp_CoUninitialize]
%line 58+0 C:\dev\ac\shortcut.src
mov eax,STR00005
mov edx,eax
push edx
call $WRITELN
L00002:
mov eax,STR00006
push eax
xor ebx,ebx
mov edx,ebx
push edx
call $GETKEY
mov esi,eax
pop eax
mov ebx,esi
mov esi,ebx
mov edi,eax
push eax
push ebx
push edi
push esi
call [__imp_lstrcmpA]
xor edx,edx
cmp eax,0
sete dl
push edx
push esi
call FreeHeap
pop edx
pop ebx
pop eax
mov eax,edx
cmp eax,dword 0
jz near dword L00003
%line 59+0 C:\dev\ac\shortcut.src
jmp L00002
L00003:
%line 61+0 C:\dev\ac\shortcut.src
mov eax,0
pop esi
pop edi
pop ebx
mov esp,ebp
pop ebp
ret
%line 63+0 C:\dev\ac\shortcut.src
.ef

;subroutine CreateLink begin
$CreateLink:
.bf
push ebp
mov ebp,esp
sub esp,_@@CreateLink_
push ebx
push edi
push esi
%line 73+0 C:\dev\ac\shortcut.src
%line 74+0 C:\dev\ac\shortcut.src
%line 74+0 C:\dev\ac\shortcut.src
lea eax,[ebp-4]
mov esi,eax
xor eax,eax
mov edx,eax
mov [esi],edx
%line 75+0 C:\dev\ac\shortcut.src
%line 76+0 C:\dev\ac\shortcut.src
%line 78+0 C:\dev\ac\shortcut.src
lea eax,[ebp-4]
push eax
lea eax,[ebp-8]
push dword [eax]
mov eax, $_IID_IShellLinkA
push eax
mov eax,1
push eax
mov eax,0
mov edx,eax
push edx
mov eax, $_CLSID_ShellLink
push eax
call [__imp_CoCreateInstance]
mov edx,eax
pop esi
mov [esi],edx
%line 80+0 C:\dev\ac\shortcut.src
xor eax,eax
lea ebx,[ebp-4]
mov esi,[ebx]
mov edi,eax
cmp esi,edi
sete dl
and edx,dword 0x000000ff
mov eax,edx
test eax,eax
jz near dword L00004
%line 81+0 C:\dev\ac\shortcut.src
mov eax,STR00007
mov edx,eax
push edx
call $WRITELN
%line 84+0 C:\dev\ac\shortcut.src
lea eax,[ebp-8]
mov edx,eax
mov edx,[edx]
mov eax,edx
mov edi,[eax]
mov eax,[ebp+8]
mov edx,eax
push edx
lea eax,[ebp-8]
mov edx,eax
mov edx,[edx]
mov eax,edx
mov edx,eax
push edx
mov edi,dword [esp]
mov edi,[edi]
call [edi+80]
%line 85+0 C:\dev\ac\shortcut.src
lea eax,[ebp-8]
mov edx,eax
mov edx,[edx]
mov eax,edx
mov edi,[eax]
mov eax,[ebp+16]
mov edx,eax
push edx
lea eax,[ebp-8]
mov edx,eax
mov edx,[edx]
mov eax,edx
mov edx,eax
push edx
mov edi,dword [esp]
mov edi,[edi]
call [edi+28]
%line 89+0 C:\dev\ac\shortcut.src
lea eax,[ebp-4]
push eax
lea eax,[ebp-8]
mov edx,eax
mov edx,[edx]
mov eax,edx
mov edi,[eax]
lea eax,[ebp-12]
push dword [eax]
mov eax, $_IID_IPersistFile
mov edx,eax
push edx
lea eax,[ebp-8]
mov edx,eax
mov edx,[edx]
mov eax,edx
mov edx,eax
push edx
mov edi,dword [esp]
mov edi,[edi]
call [edi+0]
mov edx,eax
pop esi
mov [esi],edx
%line 91+0 C:\dev\ac\shortcut.src
xor eax,eax
lea ebx,[ebp-4]
mov esi,[ebx]
mov edi,eax
cmp esi,edi
sete dl
and edx,dword 0x000000ff
mov eax,edx
test eax,eax
jz near dword L00005
%line 92+0 C:\dev\ac\shortcut.src
mov eax,STR00008
mov edx,eax
push edx
call $WRITELN
%line 93+0 C:\dev\ac\shortcut.src
%line 95+0 C:\dev\ac\shortcut.src
mov eax,260
push eax
lea eax,[ebp-532]
mov edx,eax
push edx
mov eax,1
xor edx,edx
sub edx,eax
mov eax,edx
push eax
mov eax,[ebp+12]
mov edx,eax
push edx
xor eax,eax
push eax
mov eax,0
push eax
call [__imp_MultiByteToWideChar]
%line 97+0 C:\dev\ac\shortcut.src
lea eax,[ebp-4]
push eax
lea eax,[ebp-12]
mov edx,eax
mov edx,[edx]
mov eax,edx
mov edi,[eax]
mov eax,1
push eax
lea eax,[ebp-532]
mov edx,eax
push edx
lea eax,[ebp-12]
mov edx,eax
mov edx,[edx]
mov eax,edx
mov edx,eax
push edx
mov edi,dword [esp]
mov edi,[edi]
call [edi+24]
mov edx,eax
pop esi
mov [esi],edx
%line 98+0 C:\dev\ac\shortcut.src
lea eax,[ebp-12]
mov edx,eax
mov edx,[edx]
mov eax,edx
mov edi,[eax]
lea eax,[ebp-12]
mov edx,eax
mov edx,[edx]
mov eax,edx
mov edx,eax
push edx
mov edi,dword [esp]
mov edi,[edi]
call [edi+8]
%line 100+0 C:\dev\ac\shortcut.src
L00005:
%line 100+0 C:\dev\ac\shortcut.src
lea eax,[ebp-8]
mov edx,eax
mov edx,[edx]
mov eax,edx
mov edi,[eax]
lea eax,[ebp-8]
mov edx,eax
mov edx,[edx]
mov eax,edx
mov edx,eax
push edx
mov edi,dword [esp]
mov edi,[edi]
call [edi+8]
%line 102+0 C:\dev\ac\shortcut.src
L00004:
%line 102+0 C:\dev\ac\shortcut.src
lea eax,[ebp-4]
mov edx,[eax]
mov eax,edx
pop esi
pop edi
pop ebx
mov esp,ebp
pop ebp
ret 12
%line 104+0 C:\dev\ac\shortcut.src
.ef

%line 112+0 C:\dev\ac\shortcut.src
%line 113+0 C:\dev\ac\shortcut.src
%line 114+0 C:\dev\ac\shortcut.src
%line 115+0 C:\dev\ac\shortcut.src
%line 116+0 C:\dev\ac\shortcut.src
%line 117+0 C:\dev\ac\shortcut.src
%line 118+0 C:\dev\ac\shortcut.src
%line 119+0 C:\dev\ac\shortcut.src
%line 120+0 C:\dev\ac\shortcut.src
%line 121+0 C:\dev\ac\shortcut.src
%line 122+0 C:\dev\ac\shortcut.src
%line 123+0 C:\dev\ac\shortcut.src
%line 124+0 C:\dev\ac\shortcut.src
%line 125+0 C:\dev\ac\shortcut.src
%line 126+0 C:\dev\ac\shortcut.src
%line 127+0 C:\dev\ac\shortcut.src
%line 128+0 C:\dev\ac\shortcut.src
%line 129+0 C:\dev\ac\shortcut.src
%line 130+0 C:\dev\ac\shortcut.src
%line 131+0 C:\dev\ac\shortcut.src
%line 132+0 C:\dev\ac\shortcut.src
%line 133+0 C:\dev\ac\shortcut.src
%line 134+0 C:\dev\ac\shortcut.src
%line 136+0 C:\dev\ac\shortcut.src
%line 137+0 C:\dev\ac\shortcut.src
%line 138+0 C:\dev\ac\shortcut.src
;subroutine GetFolderLocation begin
$GetFolderLocation:
.bf
push ebp
mov ebp,esp
sub esp,_@@GetFolderLocation_
push ebx
push edi
push esi
%line 141+0 C:\dev\ac\shortcut.src
%line 142+0 C:\dev\ac\shortcut.src
%line 143+0 C:\dev\ac\shortcut.src
%line 144+0 C:\dev\ac\shortcut.src
%line 145+0 C:\dev\ac\shortcut.src
lea eax,[ebp-268]
push eax
lea eax,[ebp-264]
mov edx,eax
mov eax,edx
mov edx,eax
pop esi
mov [esi],edx
%line 146+0 C:\dev\ac\shortcut.src
lea eax,[ebp-268]
push dword [eax]
lea eax,[ebp+8]
push dword [eax]
mov eax,0
push eax
call [__imp_SHGetSpecialFolderLocation]
%line 147+0 C:\dev\ac\shortcut.src
lea eax,[ebp-260]
mov edx,eax
push edx
lea eax,[ebp-264]
push dword [eax]
call [__imp_SHGetPathFromIDList]
%line 148+0 C:\dev\ac\shortcut.src
lea eax,[ebp-264]
push dword [eax]
call [__imp_CoTaskMemFree]
%line 149+0 C:\dev\ac\shortcut.src
lea eax,[ebp-260]
mov eax,eax
mov esi,eax
push esi
call _astrlen
add eax,1
push eax
call AllocHeap
push esi
push eax
call _astrcpy
pop esi
pop edi
pop ebx
mov esp,ebp
pop ebp
ret 4
%line 151+0 C:\dev\ac\shortcut.src
.ef

segment .data use32 align=4
$STR00000 db "\shell_COM_example.lnk",0
$STR00001 db "shell_COM_example.exe",0
$STR00002 db "shell_COM_example",0
$STR00003 db "Shortcut created OK!",0
$STR00004 db "Unable to create shortcut",13,10,"",0
$STR00005 db "Press any key to close",13,10,"",0
$STR00006 db "",0
$STR00007 db "IShellLinkA object created",13,10,"",0
$STR00008 db "IPersistFile object obtained",13,10,"",0

IShellLinkA_vtable_
dd $IUnknown@QueryInterface
dd $IUnknown@AddRef
dd $IUnknown@Release
dd $IShellLinkA@GetPath
dd $IShellLinkA@GetIDList
dd $IShellLinkA@SetIDList
dd $IShellLinkA@GetDescription
dd $IShellLinkA@SetDescription
dd $IShellLinkA@GetWorkingDirectory
dd $IShellLinkA@SetWorkingDirectory
dd $IShellLinkA@GetArguments
dd $IShellLinkA@SetArguments
dd $IShellLinkA@GetHotkey
dd $IShellLinkA@SetHotkey
dd $IShellLinkA@GetShowCmd
dd $IShellLinkA@SetShowCmd
dd $IShellLinkA@GetIconLocation
dd $IShellLinkA@SetIconLocation
dd $IShellLinkA@SetRelativePath
dd $IShellLinkA@Resolve
dd $IShellLinkA@SetPath


IPersistFile_vtable_
dd $IUnknown@QueryInterface
dd $IUnknown@AddRef
dd $IUnknown@Release
dd $IPersistFile@GetClassID
dd $IPersistFile@IsDirty
dd $IPersistFile@Load
dd $IPersistFile@Save
dd $IPersistFile@SaveCompleted
dd $IPersistFile@GetCurFile

segment .bss use32 align=4
$desktopPath resb 260
$objectPath resb 260
$description resb 255

Ionic Wind Support Team

Not a compiler bug.  As I said in the shell_com_example that COM wasn't officially added yet.

VTABLE's are generated for class pointers because it needs to know the offset and extern.  I got around that by using a gerneric pointer and typecasting.

In the next update there will be the 'interface' keyword.

interface IUnknown
{
...
}

interface IDispatch : IUnknown
{
...
}

The difference is a vtable isn't created locally for interfaces. 

If you want to make your code work before then just use the 'pointer type'.

pointer psl;
pointer ppf;

And typecase when accessing the COM method

*(IShellLink)psl.function();

Paul.
Ionic Wind Support Team

Parker

Okay, I get it now. Sorry for reporting a fake bug.

Bruce Peaslee

Quote from: Parker on December 16, 2005, 05:56:13 PM
Okay, I get it now. Sorry for reporting a fake bug.

I don't.  8)

Keep the questions coming. It's how we all learn.
Bruce Peaslee
"Born too loose."
iTired (There's a nap for that.)
Well, I headed for Las Vegas
Only made it out to Needles

Ionic Wind Support Team

I was typing that real fast during a work break.

A virtual class function exisits in your executable, somewhere.  It is just a subroutine afterall. So Parker was having problems with the linker/assmbler looking for a class function locally, when in fact it was part of a COM object.

My previous example worked by taking advantage of the difference between generic pointers (def a as pointer) and typed pointers (IShellDispatch *a).   A typed pointer to a class will create a VTABLE entry in the assembly file and cause the linker to look for the actual methods somewhere in your object files. 

Paul.

Ionic Wind Support Team

Ionic Wind Support Team

As a side note....don't let all of this technical jargon about vtables confuse you too much.  You don't need to understand how a class works internally just to use them. 

It's my job to hide the implimentation details as much as possible.  Forcing the compiler to use COM when it wasn't quite ready to do so precipitated the discussion in the first place ;)

Paul.
Ionic Wind Support Team

Parker

I noticed SETTYPE is highlighted in the IDE, which I know isn't a C++ keyword, would it work to do this the IBasic way:
pointer someinterface;
settype someinterface, IInterface;
*someinterface.method();

Ionic Wind Support Team

Ionic Wind Support Team