• Welcome to Jose's Read Only Forum 2023.
 

What i am especting from a bare compiler

Started by Patrice Terrier, June 06, 2010, 12:54:49 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Patrice Terrier

The purpose of the example was not about "progman" but the use of
VirtualAllocEx
OpenProcess
WriteProcessMemory
ReadProcessMemory

Anyway despite what you think, try this on Seven 64-bit

DECLARE FUNCTION FindWindow LIB "USER32.DLL" ALIAS "FindWindowA" (lpClassName AS ASCIIZ, lpWindowName AS ASCIIZ) AS LONG
FUNCTION PBMAIN
MSGBOX STR$(FindWindow("Progman", "Program Manager"))
END FUNCTION


Oh, yes i forgot that you are still running XP  ;D

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Mike Stefanik

#61
Of course there's legitimate needs for actual 64-bit code, but in your particular example, what are you exactly trying to do there? Specifically, if you want to create a shortcut, why aren't you just using the IShellLink interface? What you're doing there seems odd, and reading/writing memory for another process violates LUA (least privilege) principles.

Edit: If two processes want to share memory, there's specific APIs for that using memory-mapped files (i.e.: CreateFileMapping, MapViewOfFile, etc.) and they'll work between 32-bit and 64-bit processes. IMO, reading and writing the memory of another process, etc. should be an absolute last resort, particularly when that process is owned by the operating system. Even when code like that works today, I would always be concerned about it creating future compatibility problems. That said, I tend to be very conservative when it comes to this type of stuff.

Edwin Knoppert

It's not if progman still exists, it's being used during the old dde days for creating shortcuts, this progman stuff is simply still there but i don't think ms has given it carte blanche on keep on using it.
Like Progman.exe and control.exe (printerstuff) may still exist as well, they where there for backwards comp. reasons.

Patrice Terrier

#63
I am not trying to create a shortcut, but to retrieve all the info related to the shortcuts shown onto the desktop.

This is the code i am using now to deal with 64-bit:
SUB CreateShortCut(BYVAl hWnd AS LONG)

   LOCAL nFound, nCount, nLeft, nRight, nHeight, hBitmap, xOffset AS LONG
   LOCAL K, nItemCount, nCenter AS LONG, sLink, sUseThumb AS STRING
   LOCAL rw AS RECT

   gnXoffset = 0
   '//gS(%ID_LEFT).visible = 0
   '//gS(%ID_RIGHT).visible = 0
   IF UBOUND(gS) > 0 THEN '// Clear existing bitmap
      FOR K = 1 TO UBOUND(gS)
          IF gS(K).hBitmap THEN DeleteObject(gS(K).hBitmap): gS(K).hBitmap = 0
      NEXT
   END IF
   nCenter = (gS(0).w - 48) \ 2

   ghProgMan  = FindWindow("Progman", "Program Manager")
   ghListView = FindWindowEx(ghProgMan, 0, "SHELLDLL_DefView", "")
   ghListView = FindWindowEx(ghListView, 0, "SysListView32", "FolderView")
   nItemCount = SendMessage(ghListView, %LVM_GETITEMCOUNT, 0, 0)
   IF nItemCount THEN

      LOCAL pWsh AS IWshShell
      pWsh = NEWCOM "WScript.Shell"
      LOCAL pLnk AS IWshShortcut
'      Shortcut description:       ACODE$(pLnk.Description)
'      Shortcut working directory: ACODE$(pLnk.WorkingDirectory)
'      Shortcut arguments:         ACODE$(pLnk.Arguments)
'      Shortcut hot key:           ACODE$(pLnk.HotKey)
'      Shortcut icon location:     ACODE$(pLnk.IconLocation)
'      Shortcut target path:       ACODE$(pLnk.TargetPath)
'      Shortcut window style:      FORMAT$(pLnk.WindowStyle)

      LOCAL sDeskTopPub, sDeskTopAdm, sFullName, sTempPath AS STRING
      LOCAL DoLnk, nIconVisibleAtOnce AS LONG
      LOCAL szTxt AS ASCIIZ * %MAX_PATH

      'sDeskTopTray$ = zsFolderGet(&H000A) '// %CSIDL_BITBUCKET ' <desktop>\Recycle Bin
'      %CSIDL_STARTMENU            = &H000b  ' <user name>\Start Menu
'      %CSIDL_DESKTOPDIRECTORY     = &H0010  ' <user name>\Desktop
      sDeskTopAdm = zsFolderGet(%CSIDL_DESKTOP)
      sDeskTopPub = zsFolderGet(%CSIDL_COMMON_DESKTOPDIRECTORY)
      sTempPath = zGetTempPath()

      CALL GetWindowRect(hWnd, rw)
      nHeight = (rw.nBottom - rw.nTop) - 75

      '// Do "Recycle bin" first
      sTarget$ = "": szTxt = ShortCutDisplayName(%CSIDL_BITBUCKET): GOSUB ProcessPseudoLnk
      gnRecycleBin = nCount': gS(gnRecycleBin).IconPath = EXE.Path$ + "UserIcon\48x48\RecycleBinFull.png"
      IF gS(gnRecycleBin).hBitmap THEN DeleteObject(gS(gnRecycleBin).hBitmap): gS(gnRecycleBin).hBitmap = 0
      sUseThumb = "RecycleBinEmpty.png": gnRecycleBinFull = 0
      IF SHGetRecycleBinCount() THEN sUseThumb = "RecycleBinFull.png": gnRecycleBinFull = -1
      gS(gnRecycleBin).IconPath = EXE.Path$ + "UserIcon\48x48\" + sUseThumb
      gS(gnRecycleBin).hBitmap = CreateCustomIcon((gS(gnRecycleBin).IconPath), gS(gnRecycleBin).w, gS(gnRecycleBin).h, 0)
      gS(gnRecycleBin).ShellTo = "explorer.exe"
      gS(gnRecycleBin).CmdLine = "/N;::{645FF040-5081-101B-9F08-00AA002F954E}" '// "/N,::{645FF040-5081-101B-9F08-00AA002F954E}"
      gS(gnRecycleBin).ShowCmd = %SW_SHOW
      '// End Recycle bin

      sFullName = sDeskTopAdm + "*.lnk"
      slink = DIR$(sFullName, 39) ' %NORMAL + %READONLY + %HIDDEN + %SYSTEM + %ARCHIVE
      DO WHILE LEN(sLink)
         sFullName = sDeskTopAdm + sLink: GOSUB ProcessLnk
         sLink = DIR$
      LOOP

      sFullName = sDeskTopPub + "*.lnk"
      slink = DIR$(sFullName, 39) ' %NORMAL + %READONLY + %HIDDEN + %SYSTEM + %ARCHIVE
      DO WHILE LEN(sLink)
         sFullName = sDeskTopPub + sLink: GOSUB ProcessLnk
         sLink = DIR$
      LOOP

'      ****************************************************
'      Check for OTB file, and read/add custom shortcuts
      CALL ReadCustomShortcuts(nFound, nCount, nHeight)
'      ****************************************************
      '// Setup icon x location
      nIconVisibleAtOnce = (gS(0).w - 88) \ 48
      xOffset = 44
      IF nCount < nIconVisibleAtOnce + 1 THEN
         xOffset += ((gS(0).w - 88) - (48 * nCount)) \ 2
      END IF
      FOR K = 1 TO nCount
          gS(K).x = xOffset + (48 * (K - 1))
      NEXT

   END IF

   EXIT SUB

ProcessLnk:
   szTxt = PATHNAME$(NAME, sLink)
   pLnk = pWsh.CreateShortcut(UCODE$(sFullName))
   sTarget$ = RTRIM$(ACODE$(pLnk.TargetPath))

'af$ = sFullName +$cr + sTarget$ + $cr + _
'      "Shortcut description: >" +      ACODE$(pLnk.Description)+"<"+$cr+ _
'      "Shortcut working directory: >" +ACODE$(pLnk.WorkingDirectory)+"<"+$cr+ _
'      "Shortcut arguments: >" +        ACODE$(pLnk.Arguments)+"<"+$cr+ _
'      "Shortcut hot key: >" +          ACODE$(pLnk.HotKey)+"<"+$cr+ _
'      "Shortcut icon location: >" +    ACODE$(pLnk.IconLocation)+"<"+$cr+ _
'      "Shortcut target path: >" +      ACODE$(pLnk.TargetPath)+"<"+$cr+ _
'      "Shortcut window style: >" +     FORMAT$(pLnk.WindowStyle)+"<"
'msgbox Af$

ProcessPseudoLnk:
   DoLnk = -1
   IF LEN(sTarget$) = 0 THEN
      sTarget$ = ResolveShortcutName(szTxt)
      IF LEN(sTarget$) = 0 THEN sTarget$ = ResolveLnk((sFullName)) ELSE DoLnk = 0
   ELSEIF LCASE$(sTarget$) = LCASE$(EXE.FULL$) THEN
      sTarget$ = ""
   END IF

   IF LEN(sTarget$) THEN
      LOCAL sIconSearch AS STRING
      sIconSearch = ""
      IF DoLnk THEN sIconSearch = LCASE$(EXTRACT$(ACODE$(pLnk.IconLocation), ",")): IF RIGHT$(sIconSearch, 4) <> ".ico" THEN sIconSearch = ""
      IF LEN(sIconSearch) = 0 THEN sIconSearch = sTarget$
      INCR nFound
      IF CreateBarIcon((sIconSearch), nFound) THEN
         INCR nCount
         REDIM PRESERVE gS(%LBOUND TO nCount)
         gS(nCount).y = nHeight: gs(nCount).scale = %SCALE_DEFAULT: gS(nCount).opacity = 255
         sUseThumb = sTempPath + "OfTheBay" + STR$(nFound) + ".png"
         gS(nCount).hBitmap = CreateDockIcon((sUseThumb), gS(nCount).w, gS(nCount).h)
         CALL zKillFile((sUseThumb))
         IF DoLnk THEN gS(nCount).ShellTo = LCASE$(sTarget$)
         IF DoLnk THEN gS(nCount).WorkDir = ACODE$(pLnk.WorkingDirectory)
         IF DoLnk THEN gS(nCount).CmdLine = ACODE$(pLnk.Arguments)
         gS(nCount).UseLabel = szTxt
         IF DoLnk THEN gS(nCount).ShowCmd = pLnk.WindowStyle


         '// Check for "My computer"
         IF gS(nCount).UseLabel = ShortCutDisplayName(%CSIDL_DRIVES) THEN
            gS(nCount).ShellTo = "explorer.exe"
            gS(nCount).CmdLine = "/N;::{20d04fe0-3aea-1069-a2d8-08002b30309d}" '// "/N,::{20d04fe0-3aea-1069-a2d8-08002b30309d}"
            gS(nCount).ShowCmd = %SW_SHOW
         END IF

      END IF
   END IF

RETURN

END SUB


This was just to give an example of the first problem i had to solve, because my program was 32-bit and the OS was 64-bit.

Note: Don't be fool by the name of the procedure CreateShorCut it is not doing what you think, indeed it is something very different that the ishelllink interface.
What i am using here is the Active Desktop Object as explained here:
http://msdn.microsoft.com/en-us/library/bb776830(VS.85).aspx

If you want to figure what this program is doing, then download the GDImage project "Of The Bay" and you will get the picture ;)


Before (the Windows look)


After (the Mac OSX look)


...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

Mike,

Do you know the correct C# syntax to use fixed to pass a pointer on an array structure to an unmanaged DLL ?

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Mike Stefanik

If you want to pin variables, then you need to declare the code as unsafe. Here's a very simple example of using a pointer to an array.


    class Program
    {
        static void Main(string[] args)
        {
            int[] fooBar = new int[5];

            for (int i = 0; i < 5; i++)
            {
                fooBar[i] = i + 1;
                Console.WriteLine("fooBar[{0}] = {1}", i, fooBar[i]);
            }

            Console.WriteLine("----");

            // if you want to pin variables and manipulate pointers to them,
            // then you need to declare the code unsafe
            unsafe
            {
                fixed (int* pBar = fooBar)
                {
                    // the array is pinned and cannot be moved by the garbage collector,
                    // you can change the value of what is being pointed to
                    for (int i = 0; i < 5; i++)
                        pBar[i] += 10;

                    // You could call your unmanaged code here, passing in pBar as
                    // the pointer to the array
                    Console.WriteLine("fooBar[3] = {0}", *(pBar + 3));
                }
            }

            Console.WriteLine("----");

            for (int i = 0; i < 5; i++)
                Console.WriteLine("fooBar[{0}] = {1}", i, fooBar[i]);
        }
    }


Mike Stefanik

By the way, although that example is clearly contrived, keep in mind that you'll need to leave that array (or whaever you're passing a pointer to) pinned as long as your unmanaged code hangs on to it. What you generally do not want to do is have your unmanaged code "store" that pointer anywhere (in a context structure, global, etc.) and keep referencing it, forcing the data to be pinned for long periods of time. If you do really want to lock down a managed object, then you can use GCHandle.Alloc but it's basically the same issue; long-term pinning of objects inteferes with garbage collection so you want to keep that to a minimum.

Patrice Terrier

#67
Mike,

Here is the PB code:
 TYPE ZGLTEXTUREX
     ID       AS LONG
     FullName AS ASCIIZ * 260
     Texture  AS LONG
     Square   AS LONG            '// boolean TRUE or FALSE value
 END TYPE

Translated to C#:
       [StructLayout(LayoutKind.Sequential)]
       public struct ZGLTEXTUREX
       {
           public int ID;
           [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Api.MAX_PATH)]
           public string FullName;
           public int Texture;
           public int Square;
       }


Then i am creating the C# array this way
static GI.ZGLTEXTURE[] mt = new GI.ZGLTEXTURE[3]

and I would like to call this PB function
DECLARE FUNCTION ZI_MakeMultipleTexture ALIAS "ZI_MakeMultipleTexture" (BYVAL mt AS ZGLTEXTUREX PTR, BYVAL tArrayCount AS LONG) EXPORT AS LONG

Note: The whole project is declared "unsafe".

Should i declared the GI.ZGLTEXTURE[] mt array this way:
fixed (int* pmt = mt)


and how should i declare the ZI_MakeMultipleTexture (see the ? ? ? ?)
Quote[DllImport(GDIMAGE, EntryPoint = "ZI_MakeMultipleTexture")]
       public static extern int MakeMultipleTexture(? ? ? ?, int n);
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Mike Stefanik

Off the top of my head, I think something like this will do what you want. I modifed the structure to use a fixed byte array because the way that you had declared it, it was not a blittable type and GCHandle wouldn't be able to pin it. The only inconvenience there is that you'll need to create a helper to read/write the FullName member of the structure, rather than simply assigning it a value and let the marshaling code take care of it.


unsafe public struct ZGLTEXTUREX
{
    public int ID;
    public fixed byte FullName[260]; // or whatever the size actually is
    public int Texture;
    public int Square;
}



[DllImport("whatever.dll", EntryPoint = "ZI_MakeMultipleTexture")]
public static extern int ZI_MakeMulitpleTexture(
    IntPtr mt,
    int tArrayCount
    );



ZGLTEXTUREX[] mt = new ZGLTEXTUREX[3];
GCHandle gchmt = GCHandle.Alloc(mt, GCHandleType.Pinned); // array is pinned and cannot be GCed

result = ZI_MakeMultipleTexture(gchmt.AddrOfPinnedObject(), 3);

// do whaever else, at some point later when that structure array is no
// longer needed, make sure you free it so that it can be GCed

gchmt.Free();


Patrice Terrier

Thank you Mike, i will give it a try.

The infamous GC is the thing that discouraged me to make further advanced graphic programming in C#.  >:(

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Mike Stefanik

Quote from: Patrice Terrier on July 12, 2010, 05:40:40 PM
The infamous GC is the thing that discouraged me to make further advanced graphic programming in C#.

What you might want to consider doing is create "helper functions" that you can use in C# so that you don't have to create objects in the managed address space and then pin them. So instead of creating an array of structures, pinning it and passing a pointer, you could create some additional functions, something like: ZI_AllocMultipleTextures (allocate memory for the array, return a pointer to the base element of the array), ZI_InitializeTexture (to set the structure members), and ZI_FreeTextures (to release the memory you've allocated).

This kind of approach could have a couple of advantages. First, you could treat the return value from ZI_AllocMultipleTextures as opaque; it would be a pointer (IntPtr in C#) but it would just be a value that you could store and pass around without worrying about pinning, etc. It also would also mean that your C# code wouldn't need to to worry about what exactly the ZGLTEXTURE structure "looks like" since you would only be dealing with it using accessor functions; if you changed it in your PB code, you wouldn't have to worry about also making the corresponding change in your C# code.

Kevin Diggins

I realize I'm a little late to this dance but I noticed BCX was being
discussed earlier in this thread and thought it would be helpful to
share a perspective from Armando Rivera.  Armando has been making
inroads into making native code applications for MacOSX using BCX.
(See scrnshot)

NB: I appreciate the mature attitude allowing discussion of other
languages (like BCX) on this board, versus the PowerBasic policy that
says competing products cannot be discussed.  Oddly, the recent
discussion about RealBasic on PB's forum escaped the forum police,
probably because most of the posts about RealBasic were negative :D

Thank you.


Armando Rivera
BCX Developer
Why I Like BCX    « on: September 06, 2009, 05:29:31 AM »

Flexibility.  Power. The merging of two disparate core languages, C and Basic.

It eliminates one of my Major gripes with Basic languages: Having to create
Include files in order to use external libraries.  I've always been more of an
implementer vs an Application coder, so this is real important to me.

Granted, there are Basic languages whose teams have done a phenomenal job of translating
C Header files (FreeBasic comes to mind), but the thing that's always bugged me
is that the C Header files are already there!  I just needed a Basic that could use
them as is.

BCX is the answer, for me anyway.  It's a huge relief not having to translate C
code to Basic too, since I can just plug it in when I need to.

I've also learned a LOT by studying it's output.

Some say that it's simply a translator, but in the end EVERY language is.

In this day of ever abstracting languages, that take you further and further away
from the generated code, it's such a pleasure to be able to see what I've coded
translated into something that is fairly easy to follow, with minimal bloat.  Because
of that, I've gained a much deeper understanding and appreciation for the C language.

In other Basic porting projects that I'd worked on, I always had to contend with major
resistance to using C to speed up the porting process.  Since BCX is built from the
ground up to use C as it's core it's been real fun to use and tinker with.  All you
have to do is look at how quickly the Linux GUI came together to see the benefits
of using this approach.  Yeah, I know it's not finished but it's still very usable.

To summarize, BCX works because it "Just Works".  Being able to merge Basic and C
syntax in the same source is an awesome boost to my work flow.


AIR.

Patrice Terrier

#72
Kev,

While PowerBASIC is heavily used by most of those posting here, it is not the only language we are are using on this forum.

For example in my dedicated section you will find code for C#, C++, WinDev, and third party addon examples.

Most of us, have also a very good insight of the C programming language, because we use the core Windows SDK flat API, instead of API encapsulation.

As a third party addon provider, i feel more concerned by Visual Studio and WinDev, because they are the largest professional market for my tools (understand, people using VS and WD are used to pay for the tools they are developing with ;) ).

However, for those programming for themselves, or wanting to produce code for other platforms, BCX looks like a very good chalenger, especialy for those who are familiar with the BASIC syntax.

Thus, you are welcomed here!

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com