The MASM Forum

General => The Workshop => Topic started by: jj2007 on May 21, 2014, 10:21:19 PM

Title: Number and type of arguments required for call to C library
Post by: jj2007 on May 21, 2014, 10:21:19 PM
I have a C library that is badly documented. With PEview, I can see the exports, but not the number (and type) of arguments. So I googled a bit, and it seems consensus is "you'll have to disassemble it".

The odd thing is that my linker knows exactly the type and number of arguments - judging from the error messages.

Example:

UnzipFile LABEL NEAR
call UnzipFile
Gets assembled & linked, so the linker recognises the existence of UnzipFile

UnzipFile PROTO
call UnzipFile
Linker error unresolved external symbol '_UnzipFile@0'

UnzipFile PROTO :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
invoke UnzipFile, 1, 2, 3, 4, 5
Linker error unresolved external symbol '_UnzipFile@20'

So how does the linker recognise that definitions in the assembler source don't match those in the library? And can we get the info from the library?
Title: Re: Number and type of arguments required for call to C library
Post by: qWord on May 21, 2014, 11:04:52 PM
C calling convention? "UnzipFile PROTO C ..."
Title: Re: Number and type of arguments required for call to C library
Post by: jj2007 on May 21, 2014, 11:32:16 PM
Quote from: qWord on May 21, 2014, 11:04:52 PM
C calling convention? "UnzipFile PROTO C ..."

That makes the _ and @nn disappear, but the linker still does not recognise it... I tried 4 and 6 args, too, no success.

The source is Pascal (from here (http://sources.ru/pascal/archives/unziptmt.htm)), and calls it like this:
      rc := unzipfile ( thename, buf, r.headeroffset, 0,
      {$ifdef Windows}vk_escape{$else}27{$endif} ); {Escape interrupts}
      IF rc = unzip_ok THEN
        writeln ( 'Ok' )

Example:
FUNCTION UnzipFile conv arg_stdcall
         ( in_name : pchar;out_name : pchar;offset : longint;hFileAction : word;cm_index : integer ) : integer;
{$ENDIF}
{usage:
in_name:      name of zip file with full path
out_name:     desired name for out file
offset:       header position of desired file in zipfile
hFileAction:  handle to dialog box showing advance of decompression (optional)
cm_index:     notification code sent in a wm_command message to the dialog
               to update percent-bar
Return value: one of the above unzip_xxx codes

I can get this to assemble & link & run:
   CloseZipFile PROTO SYSCALL :DWORD
   invoke CloseZipFile, 1

... but only for Polink. MS Link complains with fatal error LNK1115: /MACHINE option required, in spite of the fact that I do supply /MACHINE:X86

If I change that to :X86J, MS Link suddenly acknowledges that a /MACHINE option was indeed specified, and throws

LINKV9 : warning LNK4012: invalid value 'X86J', must be 'ARM, EBC, IA64, MIPS, MIPS16, MIPSFPU, MIPSFPU16, SH4, THUMB, X64, or X86'; option ignored
LINKV9 : fatal error LNK1115: /MACHINE option required

Which looks really stupid (greetings to Richmond).

SYSCALL seems to work, though:include \masm32\include\masm32rt.inc
includelib unzipw.lib
.code
start:
mov ebx, esp
sub ebx, esp
CloseZipFile PROTO SYSCALL :DWORD
; int 3
push 0
invoke CloseZipFile, esp
pop ecx
print str$(eax), " retval", 13, 10
print str$(ebx), " stack difference"
exit
end start
Title: Re: Number and type of arguments required for call to C library
Post by: nidud on May 22, 2014, 12:03:42 AM
deleted
Title: Re: Number and type of arguments required for call to C library
Post by: qWord on May 22, 2014, 01:57:44 AM
Seems like that something is wrong with import library - I would simple build a new one using polib...
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 22, 2014, 02:08:46 AM
have a look at msvcrt.inc....

    c_msvcrt typedef PROTO C :VARARG

    externdef _imp__printf:PTR c_msvcrt
    crt_printf equ <_imp__printf>
Title: Re: Number and type of arguments required for call to C library
Post by: jj2007 on May 22, 2014, 03:24:23 AM
Quote from: nidud on May 22, 2014, 12:03:42 AM
UnzipFile PROTO PASCAL :DWORD, :DWORD, :DWORD, :DWORD, :DWORD

No success...

Quote from: dedndave on May 22, 2014, 02:08:46 AM
have a look at msvcrt.inc....

That's all VARARG and C, while the unzip functions are apparently stdcall and not C.
I found two workarounds - SYSCALL with polink is the only solution that works:

includelib LiteUnZip.lib

UnzipOpenFileA PROTO SYSCALL :DWORD, :DWORD, :DWORD

.code
LiteUnzip proc filename
LOCAL hLite
  mov esi, esp
  if 1
   push 0      ; works fine
   push filename
   lea eax, hLite
   push eax
   call UnzipOpenFileA
  else
   invoke UnzipOpenFileA, addr hLite, filename, 0   ; works fine, too
   sub esp, 3*4      ; stack needs "negative balancing" here!
  endif
  sub esi, esp
  deb 4, "Result & stack difference", eax, hLite, esi
  ret
LiteUnzip endp


@qWord: Thanks, but this lib is indeed built with polib...
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 22, 2014, 04:05:30 AM
i see a couple possibilities

1) have a look at Erol's Dll2Inc readme files and examples
    i tried that, and it creates an import library and an INC   :t

2) doubtful, but COM interface ?
Title: Re: Number and type of arguments required for call to C library
Post by: Vortex on May 22, 2014, 04:22:46 AM
Hi Jochen,

Analyzing the import library :

\masm32\bin\dumpbin.exe /EXPORTS unzipw.lib

ChfUnzip_Init
CloseZipFile
FileUnzip
FileUnzipEx
GetFirstInZip
GetNextInZip
GetSupportedMethods
GetUnzipDllVersion
IsZip
SetNoRecurseDirs
SetUnzipQuestionProc
SetUnzipReportProc
UnzipFile
UnzipSize
ViewZip


No any decoration information. My solution is to use a custom invoke macro not checking the number of parameters :


include     \masm32\include\masm32rt.inc
include     invoke.inc

includelib  unzipw.lib

ChfUnzip_Init   PROTO SYSCALL
CloseZipFile    PROTO SYSCALL
FileUnzip       PROTO SYSCALL
FileUnzipEx     PROTO SYSCALL
GetFirstInZip   PROTO SYSCALL
GetNextInZip    PROTO SYSCALL
GetSupportedMethods  PROTO SYSCALL
GetUnzipDllVersion   PROTO SYSCALL
IsZip                PROTO SYSCALL
SetNoRecurseDirs     PROTO SYSCALL
SetUnzipQuestionProc PROTO SYSCALL
SetUnzipReportProc   PROTO SYSCALL
UnzipFile            PROTO SYSCALL
UnzipSize            PROTO SYSCALL
ViewZip              PROTO SYSCALL

.data

test1       db 'test',0

.data?

.code

start:

    invoke  ExitProcess,0

    _invoke  SetUnzipQuestionProc,1,2,3
    _invoke  SetUnzipReportProc,1,ADDR test1,ADDR test1,4
    _invoke  FileUnzip
    _invoke  IsZip,1

END start


As I don't know the prototypes of the zip functions, I wrote some dummy function calls above.
Title: Re: Number and type of arguments required for call to C library
Post by: Gunther on May 22, 2014, 04:26:59 AM
Jochen, Erol,

Quote from: Vortex on May 22, 2014, 04:22:46 AM
As I don't know the prototypes of the zip functions, I wrote some dummy function calls above.

That's quite a fumbling. What about building it again?

Gunther
Title: Re: Number and type of arguments required for call to C library
Post by: Vortex on May 22, 2014, 04:48:11 AM
Hi Jochen,

Reading the document in :

http://sources.ru/pascal/archives/unziptmt.htm

Here is my attempt to create a .def and .lib file :

UnZipDll.def :

LIBRARY UnZipDll
EXPORTS
"_FileUnzip@20"
"_FileUnzipEx@12"
"_ViewZip@12"
"_SetUnZipReportProc@4"
"_SetUnZipQuestionProc@4"
"_UnzipSize@8"
"_ChfUnzip_Init@0"
"_SetNoRecurseDirs@4"
"_UnzipFile@20"
"_GetFirstInZip@8"
"_GetNextInZip@4"
"_IsZip@4"
"_CloseZipFile@4"
"_GetSupportedMethods@0"


\masm32\bin\polib /OUT:UnZipDll.lib /DEF:UnZipDll.def /MACHINE:x86

Could you try this one?
Title: Re: Number and type of arguments required for call to C library
Post by: Vortex on May 22, 2014, 04:52:30 AM
Hi Jochen,

Checking this project :

http://www.codeproject.com/Articles/13370/LiteZip-and-LiteUnzip

Here is my include file :

; include file generated by lib2inc V2.2

UnzipClose PROTO :DWORD
UnzipFindItemA PROTO :DWORD,:DWORD,:DWORD
UnzipFindItem equ <UnzipFindItemA>

UnzipFindItemW PROTO :DWORD,:DWORD,:DWORD
UnzipFormatMessageA PROTO :DWORD,:DWORD,:DWORD
UnzipFormatMessage equ <UnzipFormatMessageA>

UnzipFormatMessageW PROTO :DWORD,:DWORD,:DWORD
UnzipGetItemA PROTO :DWORD,:DWORD
UnzipGetItem equ <UnzipGetItemA>

UnzipGetItemW PROTO :DWORD,:DWORD
UnzipItemToBuffer PROTO :DWORD,:DWORD,:DWORD,:DWORD
UnzipItemToFileA PROTO :DWORD,:DWORD,:DWORD
UnzipItemToFile equ <UnzipItemToFileA>

UnzipItemToFileW PROTO :DWORD,:DWORD,:DWORD
UnzipItemToHandle PROTO :DWORD,:DWORD,:DWORD
UnzipOpenBuffer PROTO :DWORD,:DWORD,:DWORD,:DWORD
UnzipOpenBufferRaw PROTO :DWORD,:DWORD,:DWORD,:DWORD
UnzipOpenFileA PROTO :DWORD,:DWORD,:DWORD
UnzipOpenFile equ <UnzipOpenFileA>

UnzipOpenFileRawA PROTO :DWORD,:DWORD,:DWORD
UnzipOpenFileRaw equ <UnzipOpenFileRawA>

UnzipOpenFileRawW PROTO :DWORD,:DWORD,:DWORD
UnzipOpenFileW PROTO :DWORD,:DWORD,:DWORD
UnzipOpenHandle PROTO :DWORD,:DWORD,:DWORD
UnzipOpenHandleRaw PROTO :DWORD,:DWORD,:DWORD
UnzipSetBaseDirA PROTO :DWORD,:DWORD
UnzipSetBaseDir equ <UnzipSetBaseDirA>

UnzipSetBaseDirW PROTO :DWORD,:DWORD
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 22, 2014, 04:55:18 AM
i don't think that last one jives, Erol
different library, perhaps ?

the one Jochen is working with is (C) fPrint UK Ltd, 1998
is that info-zip, Jochen ????
Title: Re: Number and type of arguments required for call to C library
Post by: Vortex on May 22, 2014, 04:58:16 AM
Hi Dave,

If I am not wrong, UnzipOpenFileA is a member of the LiteUnzip library.
Title: Re: Number and type of arguments required for call to C library
Post by: jj2007 on May 22, 2014, 09:05:27 AM
Thanks a lot, Erol and Dave :icon14:

It is actually Jeff Glatt's LiteZip library (http://www.codeproject.com/Articles/13370/LiteZip-and-LiteUnzip):
QuoteThis project is largely based upon work by Lucian Wischik, who in turn based his work on gzip 1.1.4, zlib, and info-zip which are by Jean-Loup Gailly and Mark Adler. Lucian's code has been reworked to be written in plain C, using only the Win32 API, and packaged into 2 DLLs. (Also some improvements to error-checking, some added functionality, and code-reduction/stream-lining was accomplished.)

With your help I found a way:

-   \masm32\bin\dll2inc liteunzip.dll
-   edit LiteUnZip.inc: delete all leading underscores (dll2inc has no options?)
-   \masm32\bin\polib /OUT:LiteUnzip.lib /DEF:LiteUnZip.def /MACHINE:x86 /NOUND

Works like a charm :t
Title: Re: Number and type of arguments required for call to C library
Post by: peter_asm on May 22, 2014, 09:06:13 AM
I've seen some HLL examples that use IShellFolder to create ZIP files. (http://blog.airesoft.co.uk/2012/10/dropping-like-files-zipping-without-libraries/)
Not sure how compatible they would be with WinZip, WinRAR or 7zip but might be worth a look.
Title: Re: Number and type of arguments required for call to C library
Post by: jj2007 on May 22, 2014, 06:27:48 PM
Quote from: peter_asm on May 22, 2014, 09:06:13 AM
I've seen some HLL examples that use IShellFolder to create ZIP files. (http://blog.airesoft.co.uk/2012/10/dropping-like-files-zipping-without-libraries/)
Not sure how compatible they would be with WinZip, WinRAR or 7zip but might be worth a look.

The only comment says "The sad thing is of course that the zip compatibility is crap" - but I can't open it because you need an account there.

Besides, it looks pretty complicated. A simpler solution seems Quickly unzipping a file (http://www.codeproject.com/Tips/714387/Quickly-unzipping-a-file) by imagiro, and I've tried my luck in assembler (see attachment, RTF format), but currently I'm stuck with hilariously sick stuff like

(shldisp.h)
#ifndef __Folder_FWD_DEFINED__
#define __Folder_FWD_DEFINED__
typedef interface Folder Folder;
#endif    /* __Folder_FWD_DEFINED__ */


... and I won't have time in the coming days to dig into this can of worms :(
Title: Re: Number and type of arguments required for call to C library
Post by: nidud on May 22, 2014, 08:31:25 PM
deleted
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 22, 2014, 08:37:24 PM
Hi Jochen,

Here's what I wrote for simple zip-unzip operations - not perfect and not pure ( I forgot about releasing the object after all the work is done   :redface: ) but it works fine here

include \masm32\include\masm32rt.inc

__UNICODE__ EQU
__DEBUG__  EQU 0

IDispatch_Invoke  PROTO  :DWORD,:DWORD,:DWORD,:DWORD
IDispatch_GetIDsOfNames   PROTO :DWORD,:DWORD
SetParams PROTO  :DWORD

VARIANT STRUCT
  dw1   dd 0CCh
  dw2   dd 0CCh
  dw3   dd 0CCh
  dw4   dd 0CCh
VARIANT   ENDS

DISPPARAMS   STRUCT
  rgvarg         dd ?
  rgdispidNamedArgs dd ?
  cArgs         dd ?
  cNamedArgs        dd ?
DISPPARAMS     ENDS

IFERROR  MACRO arg
   .if    eax!=S_OK
          printf("%s FAILED with hr 0x%08X\n",arg,eax)
          print  LastError$(),13,10,0
          print "Exiting ...",13,10,0
          jmp _exit
   .endif   
          ENDM

IFDEBUG   MACRO arg
   IFDEF  __DEBUG__
          printf("%s : SUCCESS\n",arg)
   ENDIF   
          ENDM
         
FEEDBACK MACRO arg
  IFERROR   arg
  IFDEBUG   arg
           ENDM

.data   
     IID_IDispatch  GUID <00020400h,0000h,0000h,<0C0h,0h,0h,0h,0h,0h,0h,46h>>
     IID_NULL       GUID <00000000h,0000h,0000h,<0h,0h,0h,0h,0h,0h,0h,0h>>
     dpar DISPPARAMS <>
     varg VARIANT    <>
     vres VARIANT    <>   
.data?
     DISPID         dd ?,?
     pclsid         dd ?
     ppvShA         dd ?
     ppvFld         dd ?
.code
     start:
            call main
            inkey
            exit
main proc
     mov eax, uc$("Shell.Application")
     invoke   CLSIDFromProgID, eax, addr pclsid

                              FEEDBACK "CLSIDFromProgID"

     invoke   CoInitialize, NULL
     invoke   CoCreateInstance, addr pclsid,
                                NULL,
                                CLSCTX_INPROC_SERVER,
                                addr IID_IDispatch,
                                addr ppvShA

                              FEEDBACK "CoCreateInstance"
     
     ; Define the DESTINATION in the third parameter "path"
     ; Note that it must be an already EXISTING ZIP file (for zip operation)
     ;                                         or folder (for unzip operation)   

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; Below is an example of zipping of "C:\masm32\projects\TST\ZIPIT" folder
;                     to "C:\masm32\projects\TST\NEW\NEW.ZIP" zip archive
; ! REPLACE THEM with your own paths !
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

      invoke IDispatch_Invoke, ppvShA,uc$("NameSpace"),uc$("C:\masm32\projects\TST\NEW\NEW.ZIP"),addr vres
                             
                               m2m ppvFld, vres.dw3

     ; Define the SOURCE file or folder in the third parameter "path"
     ; Note that NO WILDCARDS ALLOWED for zip operation
     ; Though "C:\folder\new.zip\*" seems to work for unzip operation
       
     invoke IDispatch_Invoke, ppvFld,uc$("CopyHere"),uc$("C:\masm32\projects\TST\ZIPIT"),NULL

     _exit::

     invoke CoUninitialize
   
     ret
     
main endp


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
; PROCEDURES
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

  IDispatch_Invoke proc ppv:DWORD,member:DWORD,path:DWORD,result:DWORD
            invoke IDispatch_GetIDsOfNames,ppv,member
            invoke SetParams,path
            push NULL
            push NULL
            push result
            push offset dpar
            push 1                    ; DISPATCH_METHOD
            push 409h
            push offset IID_NULL
            push DISPID
           
            mov  edx, ppv           
            mov  ecx, [edx]
            push edx
            call dword ptr  [ecx+24] ; offset of INVOKE
            FEEDBACK "IDispatch_Invoke"
            ret
  IDispatch_Invoke endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
; WORKER SUBROUTINES
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
 
  IDispatch_GetIDsOfNames  proc  ppv:DWORD, mname:DWORD
            printf("GetIDsOfNames %s\n ",mname)
            push mname
            mov  eax,esp
            push offset DISPID       
            push 409h
            push 1
            push eax
            push offset IID_NULL
            mov  edx, ppv           
            mov  ecx, [edx]
            push edx
            call dword ptr  [ecx+20] ; offset of GetIDsOfNames
            pop  edx
            FEEDBACK "GetIDsOfNames"
            ret
  IDispatch_GetIDsOfNames endp
 
  SetParams proc wstr:DWORD
            mov     eax,wstr
            mov     varg.dw1,8       
            mov     varg.dw2,0
            mov     varg.dw3,eax
            mov     varg.dw4,0
       
            mov dpar.rgvarg, offset varg
            mov dpar.rgdispidNamedArgs,0
            mov dpar.cArgs,1
            mov dpar.cNamedArgs,0
            ret
  SetParams endp

end start
   


CONSOLE ASSEMBLE & LINK in QEDITOR
Title: Re: Number and type of arguments required for call to C library
Post by: jj2007 on May 22, 2014, 08:50:09 PM
Hi Vertograd,
On Win7-32, it crashes (with an existing zip file and an existing folder):

CLSIDFromProgID : SUCCESS
CoCreateInstance : SUCCESS
GetIDsOfNames NameSpace
GetIDsOfNames : SUCCESS
IDispatch_Invoke FAILED with hr 0x80020009
桔⁥灯牥瑡潩潣灭敬整⁤畳捣獥晳汵祬മ

Exiting ...


@nidud: Thanks, I will have a look asap.
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 22, 2014, 09:01:36 PM
0x80020009 error code  is  DISP_E_EXCEPTION
It's working fine here 
Honestly I don't know what is wrong  :(
I use ML 6.14
LOCALE ID = 409

[EDIT]: Jochen, did you create that empty(?) zip file by built-in windows means?
            Could you try this  (http://masm32.com/board/index.php?topic=2825.msg29822#msg29822) in powershell with your paths ? (just to make sure that the problem is in my code)
Title: Re: Number and type of arguments required for call to C library
Post by: jj2007 on May 22, 2014, 10:25:46 PM
I used a zip file that matches the specs at http://www.codeproject.com/Tips/257193/Easily-zip-unzip-files-using-Windows-Shell
      '1) Lets create an empty Zip File .
        'The following data represents an empty zip file .

        Dim startBuffer() As Byte = {80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, _
                                     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

I am off for a few days now, sorry. See you back on Saturday 8)
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 22, 2014, 11:06:18 PM
when you right-click, New, you can create a new "Compressed Folder"
which we all know is a file
right-click/New can use templates (premade files that exist in user folders),
or it can use data from the registry

under my version of XP.....
[HKEY_CLASSES_ROOT\.zip\CompressedFolder\ShellNew]
"Data"=hex:50,4b,05,06,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00

this format might be different for newer OS's

you can read the registry and either locate the template file or get the raw binary data to create a new (empty) ZIP file
that way, it will always be compatible with the shell functions you are about to use to put things in it
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 25, 2014, 08:52:54 AM
when i try to run Vertograd's code...
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 25, 2014, 08:57:50 AM
my guess is.....
ppv means "pointer to a pointer"
you want to pass the address of the pv variable, not the contents

or....
if the pointer is not filled when you create the interface (some sort of error creating interface)
you pass a 0, and it tries to access [00000000]

that would seem to be the case, as EDX = 0
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 25, 2014, 05:28:43 PM
...
Title: Re: Number and type of arguments required for call to C library
Post by: sinsi on May 25, 2014, 05:44:10 PM
Using the Windows zip/unzip interface is probably a bad idea.
120MB zip file (140 uncompressed) takes less than 2 seconds to unzip with WinRAR but at least 20 seconds with Explorer.
Title: Re: Number and type of arguments required for call to C library
Post by: jj2007 on May 25, 2014, 06:26:28 PM
Quote from: sinsi on May 25, 2014, 05:44:10 PM
Using the Windows zip/unzip interface is probably a bad idea.
120MB zip file (140 uncompressed) takes less than 2 seconds to unzip with WinRAR but at least 20 seconds with Explorer.

Yes, it's lousy, and it would be limited to files compressed with the built-in zipper, which most likely nobody uses.

I found a MUCH better solution in the meantime, but it requires digging into the zip file specs - which is what I'll be doing the next few days ;-)

@vertograd: my condolencies for your drive, and thanks anyway for posting this very personal code :icon14:
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 25, 2014, 06:38:39 PM
Quote from: sinsi on May 25, 2014, 05:44:10 PM
Using the Windows zip/unzip interface is probably a bad idea.
120MB zip file (140 uncompressed) takes less than 2 seconds to unzip with WinRAR but at least 20 seconds with Explorer.

Maybe it's so when it comes to system-wide backups  ... and what if you need something like FILE HISTORY for your source code ? I suppose that no one of your actively developed MASM projects is SO big .
I'm just learning to use built-in features  ;)

@DAVE:
    I've tested it on Windows XP . It crashes with access violation at 401190  :t
The reason most likely is   in " m2m ppvFld, vres.dw3" line of code
Could you try this:
Quote
     invoke IDispatch_Invoke, ppvShA,uc$("NameSpace"),uc$("C:\masm32\projects\TST\NEW\NEW.ZIP"),addr vres
                             
                              printf("vres.dw3 = %08X\n",  vres.dw3)
                               m2m ppvFld, vres.dw3
                               printf("ppvFld = %08X\n",  ppvFld)

     ; Define the SOURCE file or folder in the third parameter "path"
     ; Note that NO WILDCARDS ALLOWED for zip operation
     ; Though "C:\folder\new.zip\*" seems to work for unzip operation

Now I'll continue work on enhancing the debug output    :t

[EDIT]: All is good with that line of code here . Going to find out where that pointer is lost ...






 
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 25, 2014, 07:00:29 PM
...

 
Title: Re: Number and type of arguments required for call to C library
Post by: Gunther on May 25, 2014, 07:45:50 PM
Hi vertograd,

Quote from: vertograd on May 25, 2014, 07:00:29 PM
Your condolences are accepted but my poor hard drive isn't dead yet . It's in coma  :biggrin:
Copying of 150MB of MASM folder with all the stuff  took about 3 hours . That's what I call slow 

oh yes, that's indeed a bit slow.

Gunther
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 25, 2014, 08:32:40 PM
well - part of the problem was that i did not have the proper file and folder structure
i created the folders
\masm32\projects
\masm32\projects\TST
\masm32\projects\TST\NEW
\masm32\projects\TST\ZIPIT

i then created an empty zip file (NEW.ZIP) in the \masm32\projects\TST\NEW folder
and, i put the assembler source file in the \masm32\projects\TST\ZIPIT folder (something to zip)

now, when i run the program, it says SUCCESS on all steps
at the end, we get the "Press Any Key To Continue..." prompt
THEN, Olly pops up   :redface:
a weird state i have never seen before
the NEW.ZIP file is still empty
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 25, 2014, 08:35:08 PM
things are not properly released, but that shouldn't cause an empty zip file   :(
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 25, 2014, 09:11:01 PM
Dave, thanks again
Exactly the same behavior  here  - SUCCESS on every step ,  final crash and still empty ZIP .
It looks like ZIP folder is not registered as DROP TARGET on XP   -  drag'n'drop operation doesn't add files to ZIP
Maybe it  os version specific feature
I ran ASSOC command and it showed that ZIP folder exists as SendToTarget :
QuoteASSOC | FIND "ZF"
I created an empty file with .ZFSendToTarget extension on the Desktop and tried to drop files on it. OS asked me if I want to chose ZIP FOLDER as a default program for zip archives and only then it worked ... once  :biggrin: Next time I drop file onto it - next message box with the same question.

I'll check that final crash and try to fix it .
The lack of wanted functionality requires additional reading and testing .
For now thank you all for your feedback
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 25, 2014, 09:28:26 PM
welllll.....

after doing some reading, i am not sure that this is a very good method to zip files, anyways
it seems that, under XP, there is no way to get rid of the progress dialog box
i remember someone using zlib a while back, and creating an INC for it
worse comes to worse, PK zip is not that difficult of an algorithm to code   :P

that having been said, we should still be able to get it to work - lol
i found some very interesting reading in the Community Additions section of CopyHere

http://msdn.microsoft.com/en-us/library/windows/desktop/bb787866%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/bb787866%28v=vs.85%29.aspx)

MSDN seems to have gotten away from Community Additions - it's a shame - i have learned a lot from them

also, i seem to recall we did something similar a while ago
i wrote an interface using qWord's METHOD macro and all that
Japheth came in and made a few changes or something....

http://masm32.com/board/index.php?topic=2834.0 (http://masm32.com/board/index.php?topic=2834.0)
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 25, 2014, 09:34:02 PM
one more note....

when working with API functions like CreateFile, UNICODE paths must be prepended with '\\?\'
that rule may not apply to COM, however   :P
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 25, 2014, 09:52:25 PM
Dave,
Does DRAG'N'DROP work on ZIP folder for you?
As to whether this built-in method to zip files is good or not  - It's BUILT-IN , the DEFAULT , ready for use OUT OF THE BOX and in this role it must not be perfect.
Somewhere I read that option 4 ( hide the progress dialog ) doesn't work in scripts etc.
 
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 25, 2014, 10:17:18 PM
yes, i can drag-n-drop to zips
according to what i've read, the 4 value works on vista/win7, just not XP
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 25, 2014, 10:34:26 PM
the windows shell method probably has a couple advantages
the obvious being, it's built-in
and - it will handle special locations like "My Documents" for you
also - it will do the recursion for you

on the other hand, disadvantages...
you get the dialog under xp
you may have UAC issues under vista or win7/8
it probably uses the windows shell copy algo, which doesn't always copy everything
(files like desktop.ini files that are marked do not copy or zero-length files, etc)
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 26, 2014, 12:22:17 AM
The final crash is fixed now!
Simply comment out "inkey" macro call . That's all.
Still have no idea why it doesn't zip files ...
Title: Re: Number and type of arguments required for call to C library
Post by: adeyblue on May 26, 2014, 12:49:36 AM
Quote from: dedndave on May 25, 2014, 10:34:26 PM
on the other hand, disadvantages...
you get the dialog under xp
you may have UAC issues under vista or win7/8
it probably uses the windows shell copy algo, which doesn't always copy everything
(files like desktop.ini files that are marked do not copy or zero-length files, etc)

It also runs on a separate, unwaitable and unstoppable thread, which is a plus or minus depending on your perception of things. At least in the Win7 version (which is the only one I've really looked at), there is no way to disable the progress dialog. You only see it sometimes because it's an IProgressDialog, which runs the actual dialog on another thread. If the zipping finishes before the dialog's done it's initializing, you'll never see it.

The separate zipping thread is probably the reason for the 0 length zips. You'd have to wait for it to finish before calling ExitProcess, but as zipfldr uses SHCreateThread which doesn't give you a thread handle or the thread id, it can't even wait for the zipping to finish, never mind us mortals on the outside.

Let's just say that it's not the most robust piece of multi-threaded programming ever seen.

Oh and hi :) I wrote the necessarily hacky monstrosity that peter_asm linked to in post 16.

EDIT:
Totally forgot, the preceeding applies to dragging and dropping, whether from explorer or simulated. The IStorage/IStream interfaces don't use a separate thread, but I can't ever get them to work. I'll have a look at what underlying method the scripting interface uses.
Title: Re: Number and type of arguments required for call to C library
Post by: jj2007 on May 26, 2014, 01:52:23 AM
Quote from: adeyblue on May 26, 2014, 12:49:36 AM
Oh and hi :) I wrote the necessarily hacky monstrosity that peter_asm linked to in post 16.

You mean IShellFolder to create ZIP files (http://blog.airesoft.co.uk/2012/10/dropping-like-files-zipping-without-libraries/) in post #15? Looks pretty advanced, you know your COM, also at (dis)assembly level ;-)

Welcome to the Forum :icon14:
Title: Re: Number and type of arguments required for call to C library
Post by: Gunther on May 26, 2014, 02:25:36 AM
Hi adeyblue,

Quote from: adeyblue on May 26, 2014, 12:49:36 AM
Oh and hi :) I wrote the necessarily hacky monstrosity that peter_asm linked to in post 16.

Hats off.  :t And welcome to the forum.

Gunther
Title: Re: Number and type of arguments required for call to C library
Post by: adeyblue on May 26, 2014, 03:10:33 AM
Quote
You mean IShellFolder to create ZIP files in post #15?

Yep, that's the one. Shame I can't count. It is a monstrostity though, going through the IContextMenu and simulating pasting the files on the zip is a lot easier and smaller than setting up custom dataobjects and droptargets (at least when using certain c++ features anyway - http://pastebin.com/pNjfLjWn).

Anyway, the IShellDispatch method of zipping simulates a drag and drop, so it follows what I said above. I checked the XP SP0 version of zipfldr.dll and that uses CreateThread instead of SHCreateThread. Any hope of it waiting for zipping to complete dies there though, as it promptly ignores the thread handle and leaks it.
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 26, 2014, 04:06:36 AM
Hello and welcome , adeyblue
Your article was an answer to my question  in this thread (http://masm32.com/board/index.php?topic=2825.msg29815#msg29815)
Thanks for your explanations  :icon14:
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 26, 2014, 02:07:38 PM
hi adeyblue  :t

well - i get up to the point where i have to assign one of the ID'ed namespaces to an object
then, it gets a little fuzzy - lol
it looks easy in C, but
1) there is a lot of material to read about Shell.Application
2) i can't really find the specific docs i am looking for
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 26, 2014, 05:00:05 PM
Dave,
Now I can do drag'n'drop on zips too ... so the Windows XP knows how to do it  BUT WHY WE DON'T?
Adeyblue's approach is a bit complicated to try it in MASM
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 27, 2014, 02:40:56 AM
well - the idea seems simple enough

i don't know what language this is - python or something - lol

Set sa = CreateObject("Shell.Application")
Set zip= sa.NameSpace(zipFile)
Set Fol=sa.NameSpace(FolderToZip)
zip.CopyHere(Fol.Items)


but - setting a folder is a 2 step process
1) get the id
2) set the property (i guess it's a property)

i can get the id, fine
and - CopyHere seems easy
it's that "set the folder" part that i don't understand
it seems to be done with IDispatch::Invoke

i wish i had a working C++ source and EXE to look at   :(
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 27, 2014, 04:12:15 AM
in fact, i think this would work

CoCreateInstance
IDispatch::GetIDsOfNames          ;source folder
IDispatch::Invoke                 ;set source folder - this is the part i can't get going
IDispatch::GetIDsOfNames          ;target folder
IDispatch::CopyHere(idTarget)
IDispatch::Release
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 27, 2014, 04:12:43 AM
Yes , it's simple : 3 lines of code in powershell
That's why I've implemented it in MASM and it worked JUST FINE on my machine .
The code you posted looks like VisualBasic script  and you may try to run it with WSCRIPT
Here (http://masm32.com/board/index.php?topic=2825.msg29755#msg29755) is a link to an advanced VBasic Script:
http://stackoverflow.com/questions/30211/can-windows-built-in-zip-compression-be-scripted
I'll try it on my Windows XP . I want to know if this simple method works in VBasic Script and powershell on XP .
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 27, 2014, 04:14:58 AM
scripts don't help us, much
i need a working C++ source and EXE   :t
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 27, 2014, 04:16:49 AM
Quote from: dedndave on May 27, 2014, 04:12:15 AM
in fact, i think this would work

CoCreateInstance
IDispatch::GetIDsOfNames          ;source folder
IDispatch::Invoke                 ;set source folder - this is the part i can't get going
IDispatch::GetIDsOfNames          ;target folder
IDispatch::CopyHere(idTarget)
IDispatch::Release


You're wrong , Dave
The first call to GetIDsOfNames obtains Namespace member and IT'S THE TARGET FOLDER
My code is alright except that I don't call  Release method

[EDIT]: Oh, I understood now - we're obtaining folder interface for both source and target . Worth a try . Usually I try  scripts first .

Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 27, 2014, 04:21:42 AM
Quote from: dedndave on May 27, 2014, 04:14:58 AM
scripts don't help us, much
i need a working C++ source and EXE   :t
They can help us  - if we will know that this "simple method"  works in scripts on XP  then we may be sure that the reason is in my code and not in OS
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 27, 2014, 04:22:24 AM
well - that may not be the way your example works
but, it seems logical - and i seem to recall seeing code like that browsing around the web
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 27, 2014, 04:23:36 AM
the point of having an EXE (with source helps) is that we can see the generated code
we can't do that with scripts
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 27, 2014, 04:32:23 AM
...
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 27, 2014, 04:37:44 AM
thanks   :t

this is my code, so far
if i get it working, i will add error reports (or sooner, if needed - lol)
and, i even have a way to wait for it to finish writing the zip   :biggrin:

notice, i used different paths for the test files

                  CLSIDFromProgID: Success
                 CoCreateInstance: Success
IDispatch::GetIDsOfNames(Source): Success
               IDispatch::Release: Success

Press any key to continue ...
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 27, 2014, 04:45:51 AM
Dave , could you post  the essential parts of your code  in "CODE" tags , please - I don't have an opportunity to download files here  :(
Title: Re: Number and type of arguments required for call to C library
Post by: adeyblue on May 27, 2014, 04:52:25 AM
If you still need it, here's a C++ exe and src (http://blog.airesoft.co.uk/code/zipstuff.zip). It uses IShellDispatch and the Folder interfaces directly since basic IDispatch and me aren't friends. I'll rework it to use those if you need to see what that looks like.
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 27, 2014, 04:59:05 AM
thanks, adeyblue   :t

vertograd...
the biggest difference between my code and yours is that i use qWord's METHOD macro
it simplifies the IDispatch calls   :biggrin:

;***********************************************************************************************

;METHOD macro by qWord

METHOD  MACRO   name,args:VARARG
        LOCAL   _type1,_type2
        _type1  TYPEDEF PROTO args
        _type2  TYPEDEF PTR _type1
        EXITM   <name _type2 ?>
        ENDM

;###############################################################################################

;IDispatch Interface

IDispatch STRUCT
  METHOD(QueryInterface,   _this:LPVOID,riid:LPVOID,ppvObj:LPVOID)
  METHOD(AddRef,           _this:LPVOID)
  METHOD(Release,          _this:LPVOID)
  METHOD(GetTypeInfoCount, _this:LPVOID,pctinfo:UINT)
  METHOD(GetTypeInfo,      _this:LPVOID,iTInfo:UINT,lcid:LCID,ppTInfo:LPVOID)
  METHOD(GetIDsOfNames,    _this:LPVOID,riid:LPVOID,rgszNames:LPOLESTR,cNames:UINT,lcid:LCID,rgDispId:LPVOID)
  METHOD(dInvoke,          _this:LPVOID,dispIdMember:DWORD,riid:LPVOID,lcid:LCID,wFlags:DWORD,pDispParams:LPVOID,pVarResult:LPVOID,pExcepInfo:LPVOID,puArgErr:UINT)
IDispatch ENDS


then, the calls are easy...
    print   offset sz0001
    INVOKE  CLSIDFromProgID,offset szShell,offset pClsId
    .if eax==S_OK
        print   offset szSuccess
        print   offset sz0002
        INVOKE  CoCreateInstance,offset pClsId,NULL,CLSCTX_INPROC_SERVER,offset IID_IDispatch,offset pvShell
        .if eax==S_OK
            print   offset szSuccess
            print   offset sz0003
            mov     edx,pvShell
            mov     ecx,[edx]
            INVOKE  IDispatch.GetIDsOfNames[ecx],edx,offset IID_NULL,offset adwObjSource,1,409h,offset adwDispIdSource
            .if eax==S_OK
                print   offset szSuccess

       ;         print   offset sz0004





            .endif
            print   offset sz0009
            mov     edx,pvShell
            mov     ecx,[edx]
            INVOKE  IDispatch.Release[ecx],edx
            .if eax==S_OK
                print   offset szSuccess
            .endif
        .endif
    .endif
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 27, 2014, 05:06:16 AM
Thanks,  Dave

[EDIT]: I've detected the first mistake in my code: the call to CopyHere doesn't return status SUCCESS because  as stated here (http://msdn.microsoft.com/en-us/library/windows/desktop/bb787866(v=vs.85).aspx) :
QuoteReturn value

This method does not return a value.
Remarks

No notification is given to the calling program to indicate that the copy has completed.

This VBScript is zipping the file / folder only if I call the MessageBox after CopyHere :

SET o=CreateObject("Shell.Application")
SET n=o.Namespace("C:\new.zip")
n.CopyHere("C:\myfolder")
Wscript.Echo "Please, wait"


My code requires major fixes ... I'll be back in a day or two  ;)

Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 28, 2014, 12:26:10 AM
i think i am starting to understand the interface a little bit   :P
i can see that you were right - CopyHere wants the source
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 28, 2014, 12:43:23 AM
something like this

CLSIDFromProgID
CoCreateInstance
IDispatch::GetIDsOfNames(szTarget)
IDispatch::Invoke(Shell.NameSpace(idTarget))
IDispatch::GetIDsOfNames(szSource)
IDispatch::Invoke(Folder.CopyHere(idSource))
(wait for it to finish)
IDispatch::Release


i'm getting closer, at least   :biggrin:
Title: Re: Number and type of arguments required for call to C library
Post by: peter_asm on May 28, 2014, 02:00:24 AM
i was thinking how to wait on thread termination and ExecNotificationQueryAsync might work, see vbscript for basic example


option explicit

Dim sink, end_query, wmi, shell, zip, completed

Set wmi = GetObject("WINMGMTS:\\.\root\cimv2")

Set sink = WScript.CreateObject ("WbemScripting.SWbemSink", "SINK_")

' query to monitor for deletion of threads
end_query  = "SELECT * FROM __InstanceDeletionEvent " & _
             "WITHIN 1 "                              & _
             "WHERE TargetInstance ISA 'Win32_Thread'"
               
completed = False
wmi.ExecNotificationQueryAsync sink, end_query

set shell=CreateObject("Shell.Application")
set zip=shell.Namespace("C:\users\pete\desktop\test.zip")


   ' http://msdn.microsoft.com/en-us/library/bb787866(VS.85).aspx
   ' ===============================================================
   ' 4 = do not display a progress box
   ' 16 = Respond with "Yes to All" for any dialog box that is displayed.
   ' 128 = Perform the operation on files only if a wildcard file name (*.*) is specified.
   ' 256 = Display a progress dialog box but do not show the file names.
   ' 2048 = Version 4.71. Do not copy the security attributes of the file.
   ' 4096 = Only operate in the local directory. Don't operate recursively into subdirectories.
   
   ' even though ignore is specified, a dialog box still gets displayed
Call zip.CopyHere("C:\test_folder", 4)

WScript.StdOut.Write "Please wait"

Do While Not completed
  WScript.Sleep 500
  WScript.StdOut.Write "."
Loop

WScript.StdOut.WriteLine vbCrLf & "Complete"

' notifys when thread is ending
Sub SINK_OnObjectReady(ByVal objWbemObject, ByVal objWbemAsyncContext)
  completed = True
End Sub



If i try using wildcards, it just complains about file being too long.
pity MS don't have a built in wait feature for this. i suppose because it's part of explorer and explorer always running, no need.

implementing this solution as C++ would mean inheriting from IWbemObjectSink and I've no idea how that would be done using assembly so it's probably more pain than it's worth.

found another script example : https://github.com/ynkdir/winscript/blob/master/bin/zip.bat
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 28, 2014, 02:25:17 AM
my thinking was...

if i can open the zip file for write, it must be done   :biggrin:
windows will put a lock on the zip file while processing
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 28, 2014, 03:16:54 AM
Quote from: dedndave on May 28, 2014, 12:43:23 AM
something like this

CLSIDFromProgID
CoCreateInstance
IDispatch::GetIDsOfNames(szTarget)
IDispatch::Invoke(Shell.NameSpace(idTarget))
IDispatch::GetIDsOfNames(szSource)
IDispatch::Invoke(Folder.CopyHere(idSource))
(wait for it to finish)
IDispatch::Release


i'm getting closer, at least   :biggrin:
One remark :  GetIDsOfNames takes a IDispatch member name as a parameter  - "Namespace" or "CopyHere" and returns its DISPID .

Title: Re: Number and type of arguments required for call to C library
Post by: adeyblue on May 28, 2014, 07:48:13 AM
For closure, I got my head around the workngs of the zipfldr's IStorage / IStream interfaces (which don't create a separate thread nor any UI when zipping) and they're bugged :(
They create a temporary directory fine, then an IBindCtx that'll make the shell create the file if it doesn't exist, all good so far. Unfortunately they then blunder transforming the filesystem path to a pidl: they call SHILCreateFromPath, which requires the path to already exist, instead of SHSimpleIDListFromPath which doesn't. They then call the function that uses the IBindCtx and would create the file, but since the transfomation fails they never get that far.

Shame really since it's not that much more code to use them.

Quote
if i can open the zip file for write, it must be done   
windows will put a lock on the zip file while processing
You'll have to make sure it's already opened the file before you try to, otherwise it'll probably fail (it uses FILE_SHARE_READ when calling CreateFile).
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 28, 2014, 10:40:58 AM
i think you misunderstand

you start the ZIP thread
perhaps, wait a few hundred microseconds (give it a chance to get started)
then, you attempt to open the ZIP file (probably with FILE_SHARE_WRITE flag)
if it fails, it means the ZIP thread still has the file locked (wait a few hundred microseconds, try again)
when you can successfully open the ZIP file,
it means the ZIP thread has released it - you close the handle and exit

there's probably some cleaner way to test the file lock flag (more COM stuff   ::) )
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 28, 2014, 10:48:43 AM
Quote from: vertograd on May 28, 2014, 03:16:54 AM
One remark :  GetIDsOfNames takes a IDispatch member name as a parameter
"Namespace" or "CopyHere" and returns its DISPID .

thanks vertograd

what i am trying to figure out, is how to determine what "named methods or classes" are available for a specific type of object

i found a COM book online - a lot of material to read
eventually, i'll work my way through it
for now, i just want to read enough to get past this one thing - lol
Title: Re: Number and type of arguments required for call to C library
Post by: peter_asm on May 28, 2014, 12:34:12 PM
Would be neat to see way using COM API to monitor when the thread ends.
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 28, 2014, 01:48:56 PM
normally, we could use GetExitCodeThread
but - that requires a thread handle
don't guess you have that - it may be possible to get it (difficult with no thread id)

it might be easier to get a thread count
might be something for that in the TEB
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 28, 2014, 02:09:52 PM
just a thought...

GetProcessHandleCount

http://msdn.microsoft.com/en-us/library/windows/desktop/ms683214%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms683214%28v=vs.85%29.aspx)
Title: Re: Number and type of arguments required for call to C library
Post by: jj2007 on May 28, 2014, 03:20:53 PM
afaik WaitForSingleObject can take a process handle, too.
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 28, 2014, 04:44:37 PM
Quote from: dedndave on May 28, 2014, 10:48:43 AM

thanks vertograd

what i am trying to figure out, is how to determine what "named methods or classes" are available for a specific type of object

i found a COM book online - a lot of material to read
eventually, i'll work my way through it
for now, i just want to read enough to get past this one thing - lol

All is simple - search on msdn or dig into headers in Windows SDK
NameSpace is a member of Shell object (http://msdn.microsoft.com/en-us/library/windows/desktop/bb774094(v=vs.85).aspx) 
CopyHere is a member of Folder object (http://msdn.microsoft.com/en-us/library/windows/desktop/bb787868(v=vs.85).aspx) (you can get there following the link in NameSpace description)

Another way is to use powershell . It's completely object-oriented
To create Shell object:
$shApp=New-Object -ComObject Shell.Application
To dump its members:
$shApp | Get-Member
To create Folder object:
$oFolder=$shApp.Namespace("C:\")
To dump its members:
$oFolder | Get-Member
and so on
You may learn COM with powershell  :t








Title: Re: Number and type of arguments required for call to C library
Post by: Gunther on May 28, 2014, 05:06:17 PM
Hi vertograd,

Quote from: vertograd on May 28, 2014, 04:44:37 PM
Another way is to use powershell . It's completely object-oriented
To create Shell object:
$shApp=New-Object -ComObject Shell.Application
To dump its members:
$shApp | Get-Member
To create Folder object:
$oFolder=$shApp.Namespace("C:\")
To dump its members:
$oFolder | Get-Member
and so on
You may learn COM with powershell  :t

Wow. I've done it a wide berth around powershell in the past. Was that an error?

Gunther
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 28, 2014, 07:48:38 PM
Quote from: Gunther on May 28, 2014, 05:06:17 PM
...
Wow. I've done it a wide berth around powershell in the past. Was that an error?
...
Hi Gunther,
I don't think so . It's a matter of personal preferences, your free time and professional interests.

@Dave
FIRST SUCCESS HERE ! 
On my P3 with 128MB RAM I must give zipfldr some time to finish its work :
Quote
invoke Sleep,10000
_exit::
Only 10 seconds and posted above asm source was zipped  :biggrin:
"Sleep" is not the best solution though
I'll think about thread / file lock monitoring ...
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 28, 2014, 09:10:45 PM
nice job   :t

PowerShell is very cool
however, the user may not have it installed
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 28, 2014, 09:24:50 PM
Quote from: dedndave on May 28, 2014, 09:10:45 PM
nice job   :t

PowerShell is very cool
however, the user may not have it installed

Powershell is included in Windowws 7 and can be downloaded for Windows XP  from here (http://support.microsoft.com/kb/968929)
For detailed instructions read this (http://blogs.technet.com/b/heyscriptingguy/archive/2011/01/28/install-powershell-on-windows-xp-and-copying-files.aspx)

Remarks:
Powershell requires appropriate .NET Framework pack   
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 28, 2014, 09:43:29 PM
yah - i have it installed and .NET 1.0, 1.1, 2.0, 3.0, 3.5 i think
i can't install 4.0+ because it is incompatible with XP Media Center Edition   :(

later today, i may do some more COM reading
Title: Re: Number and type of arguments required for call to C library
Post by: jj2007 on May 28, 2014, 11:10:56 PM
Folks,

I am watching with fascination and some envy your efforts to tame the COM beast :t

In the meantime, I've given up and went, as far as un-zipping is concerned, for a third party library provided by the fabulous Jørgen Ibsen (http://ibsensoftware.com/download.html) - one or two k extra, fast and comfortable ;-)

Here is a demo from \Masm32\MasmBasic\MbGuide.rtf, using UnzipInit, UnzipFile() and UnzipExit:

include \masm32\MasmBasic\MasmBasic.inc  ; version 28 May 2014 required (http://masm32.com/board/index.php?topic=94.0)
  Init
  UnzipInit "test.zip"      ; expects a filename, returns a comment (if present); edx has #records
  .if Sign?
      Print eax      ; print an error message
  .else
      push eax      ; UnzipInit returns a comment or an empty string
      For_ ecx=0 To edx-1      ; #files returned in edx
            mov esi, Files$(ecx)
            PrintLine Str$(GfSize(ecx)), Tb$, GfDate$(ecx), Spc2$, GfTime$(ecx), Tb$, esi
            .if Instr_(esi, ".asm", 1)      ; assembler source, plain text?
                  PrintLine "##First 60 chars: [", Left$(UnzipFile(ecx), 60), "]"
            .endif
      Next
      pop eax
      Print "Zipfile comment: [", eax, "]"
      UnzipExit
  .endif
  Exit
end start
Rem
- decompresses files in zip archive to a buffer returned by UnzipFile(ecx)
- you may save the file as FileWrite Cat$("\SomeFolder\"+Files$(ecx)), UnzipFile(ecx)


Sample output:
20222   19.04.2011  14:33:14    Irvine32Mb.lib
9451    02.12.2011  15:26:26    IrvineMacsMb.asm
##First 60 chars: [.NOLIST
COMMENT ! ** for use with MB - nothing adapted here]
3318    10.12.2012  09:40:28    IrvineMasm32.asc
16274   02.12.2011  15:18:26    IrvineSmallWinMb.inc


When your COM version is ready, we can start the timings thread in the Laboratory.
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 29, 2014, 03:49:42 AM
we're close, Jochen
i may work on it, if i have some time later today
but Vertograd may get one going, first - lol
Title: Re: Number and type of arguments required for call to C library
Post by: peter_asm on May 29, 2014, 08:48:06 AM
Quote from: jj2007 on May 28, 2014, 03:20:53 PM
afaik WaitForSingleObject can take a process handle, too.

Could enumerate threads with Thread32First/Thread32Next (http://msdn.microsoft.com/en-us/library/windows/desktop/ms686728%28v=vs.85%29.aspx) then call WaitForMultipleObjects()

Or enumerate all threads before calling CopyHere() and then after, using WaitForSingleObject() on new handle.

I find it strange there isn't some way to wait on thread termination through COM API..
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 29, 2014, 08:58:27 AM
i am sure COM provides a way - we just don't know what it is yet - lol

have been reading a bit
they have something called "thread apartments"
not sure that applies here, but it looks about right (haven't finished reading that part)

if you want to see some COM code, i suspect you could disassemble Explorer and some of the DLL's to see how it's done
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 29, 2014, 06:31:29 PM
...

Title: Re: Number and type of arguments required for call to C library
Post by: jj2007 on May 29, 2014, 09:39:05 PM
Quote from: vertograd on May 29, 2014, 06:31:29 PMThe Windows , ohh,  it's huge  , it's like the ocean . The ocean never meets fast brooks  ;)

Indeed. I have timed the unzipping of the 1.7->17MB database in my spreadsheet viewer (http://masm32.com/board/index.php?topic=3231.0), and it's around 340 ms on my trusty old Celeron. I doubt that Explorer can compete :biggrin:
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 29, 2014, 09:46:04 PM
i unzipped a fairly large archive the other day
333 Mb zipped, 640 Mb unzipped
took forever - lol
well - i have to wonder if the algorithm used for zipping wasn't kind of old
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 30, 2014, 01:19:01 AM
Quote from: peter_asm on May 28, 2014, 02:00:24 AM
i was thinking how to wait on thread termination and ExecNotificationQueryAsync might work, see vbscript for basic example
...
implementing this solution as C++ would mean inheriting from IWbemObjectSink and I've no idea how that would be done using assembly so it's probably more pain than it's worth.
...
Thanks peter_asm,
your suggestion to use WMI  IWbemServices interface method  ExecNotificationQueryAsync  (http://msdn.microsoft.com/en-us/library/aa392106(v=vs.85).aspxhttp://msdn.microsoft.com/en-us/library/aa392106(v=vs.85).aspx) seems to be the reasonable way to monitor threads .
I've found COM API for WMI (http://msdn.microsoft.com/en-us/library/aa389276(v=vs.85).aspx) reference and C++ Example: Receiving Event Notifications Through WMI (http://msdn.microsoft.com/en-us/library/aa390425(v=vs.85).aspx)
That's all I need for now
So ... my path lies to WMI   :biggrin:
As soon as I restore my development machine I'll dive into WMI coding in MASM 

P.S.: WaitForSingleObject / WaitForMultipleObjects require thread(s) handle(s) in parameters . Enumerating threads with Thread32First/Thread32Next  functions we get only thread IDs . However we can count the total number of threads with their help. I've already have this code written but can not re-assemble it because it wants modified kernel32.lib which I've lost with my HD .   
Title: Re: Number and type of arguments required for call to C library
Post by: adeyblue on May 30, 2014, 02:19:55 AM
Quote from: dedndave on May 29, 2014, 09:46:04 PM
well - i have to wonder if the algorithm used for zipping wasn't kind of old
The older versions of zipfldr have various 'Dynazip' strings in them, so it looks like they licensed their code rather than writing it from scratch. That product had been alive since 1996-ish so yeah, I'd guess explorer's zip algorithm is older than it is!

Quote from: vertograd
As soon as I restore my development machine I'll dive into WMI coding in MASM 
I don't envy that :) I think it's painful and long enough in C++, it must be like War & Peace in assembly.

I tried two other notification methods of various complexity. You can register for Shell change notifications on the zip file with SHChangeNotifyRegister (http://msdn.microsoft.com/en-gb/library/windows/desktop/bb762120(v=vs.85).aspx), downside is it requires creating a window and a message loop.

There's also the WinEvent hooks (http://msdn.microsoft.com/en-us/library/windows/desktop/dd373640(v=vs.85).aspx) and their window creation/deletion callback. Set one for the current process, determine when the compressing dialog has been created, then wait the reciprocal delete where you signal that it's finished and exit the app. Downside is it requires Microsoft not to change the window properties of the compressing dialog
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on May 30, 2014, 03:01:31 AM
...
Title: Re: Number and type of arguments required for call to C library
Post by: peter_asm on May 30, 2014, 04:33:04 AM
adeyblue, just added function to monitor thread termination using Thread32First/WaitForMultipleObjects but it's just a hack to show how it might work. Would cause problems where process threads > MAXIMUM_WAIT_OBJECTS (64) or lots of other thread activity going on..unreliable.

Also looked inside zipfldr.dll to see how it works there but still unsure.
Seems to be based on window notifications posted to explorer.

Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 30, 2014, 04:52:18 AM
i've been reading up a little on COM....

it would seem that the shell is a "dual interface"
that is, it may be accessed via IDispatch, or via the shell functions
from what i gather, the IDispatch methods target "variable type" languages, such as scripts
VB scripts and java scripts use IDispatch

so, it would seem that adeyblue has the right idea for what we want
however - that's not to say that it can't be done via IDispatch

a good analogy might be using DialogBoxParam and a bunch of structures to create a dialog box,
as opposed to using a resource template, and letting the OS do it

still playing with IDispatch - i want to see if i can figure it out - lol
Title: Re: Number and type of arguments required for call to C library
Post by: peter_asm on May 30, 2014, 07:45:04 AM
I was poking through zipfldr.dll again and noticed various objects used to work with ZIP files inherit from ITransferHelper, ITransferAdviseSink and ITransferSource2 which is undocumented

seen this too : http://blog.airesoft.co.uk/2012/10/dropping-like-files-zipping-without-libraries/
Title: Re: Number and type of arguments required for call to C library
Post by: jj2007 on May 30, 2014, 08:00:10 AM
Quote from: peter_asm on May 30, 2014, 07:45:04 AMseen this too : http://blog.airesoft.co.uk/2012/10/dropping-like-files-zipping-without-libraries/

That is adeyblue's blog, see reply #40 (http://masm32.com/board/index.php?topic=3215.msg33750#msg33750). Does anybody have a Microsoft account?
QuoteThe sad thing is of course that the zip compatibility is crap; http://blogs.msdn.com/b/michkap/archive/2012/01/04/10252916.aspx etc
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 30, 2014, 09:44:17 AM
i checked it the other day
it's a dead link
you can create a hotmail acct to sign into MS - it's free
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on May 30, 2014, 09:48:32 AM
it's Michael Kaplan
you can google and find that they are refering to zipping UNICODE filenames
the locale identifier may cause issues (zip in one locale, unzip in another)
seems to me, you could set the locale id to 0   :P
Title: Re: Number and type of arguments required for call to C library
Post by: jj2007 on May 30, 2014, 03:25:27 PM
Here is a sample for testing...

I can handle it with the new UnzipFile macro, but it's a bit clumsy. Curious to see if Windows knows about Unicode ;)
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 02, 2014, 12:11:05 PM
i had a little time to play, today

as i mentioned before - there is a lot of documentation on creating a COM interface
it almost seems easier than using one - lol
but, one of the things i noticed was that IDispatch interfaces aren't necessarily limited to the 7 functions
the first 3 are IUnknown, which is a subset of IDispatch, which is a subset.... and so on

IDispatch STRUCT
  METHOD(QueryInterface,   _this:LPVOID,riid:LPVOID,ppvObj:LPVOID)
  METHOD(AddRef,           _this:LPVOID)
  METHOD(Release,          _this:LPVOID)
  METHOD(GetTypeInfoCount, _this:LPVOID,pctinfo:UINT)
  METHOD(GetTypeInfo,      _this:LPVOID,iTInfo:UINT,lcid:LCID,ppTInfo:LPVOID)
  METHOD(GetIDsOfNames,    _this:LPVOID,riid:LPVOID,rgszNames:LPOLESTR,cNames:UINT,lcid:LCID,rgDispId:LPVOID)
  METHOD(dInvoke,          _this:LPVOID,dispIdMember:DWORD,riid:LPVOID,lcid:LCID,wFlags:DWORD,pDispParams:LPVOID,pVarResult:LPVOID,pExcepInfo:LPVOID,puArgErr:UINT)
IDispatch ENDS


what i learned was, because we are using "Shell.Application",
what we are actually getting is an IShellDispatch interface vTable
and - with different versions of OS, service pack, CommonCtrls, and .NET, you get different versions of IShellDispatch
using XP SP3, .NET 3.5, and without referencing CommCtrls 6.0, i get an IShellDispatch4 vTable
these can be acquired directly with
IID_IShellDispatch  GUID <0D8F015C0h,0C278h,11CEh,<0A4h,9Eh,44h,45h,53h,54h,0,0>>
IID_IShellDispatch2 GUID <0A4C6892Ch,3BA9h,11D2h,<9Dh,0EAh,0,0C0h,4Fh,0B1h,61h,62h>>
IID_IShellDispatch3 GUID <177160CAh,0BB5Ah,411Ch,<84h,1Dh,0BDh,38h,0FAh,0CDh,0EAh,0A0h>>
IID_IShellDispatch4 GUID <0EFD84B2Dh,4BCFh,4298h,<0BEh,25h,0EBh,54h,2Ah,59h,0FBh,0DAh>>
IID_IShellDispatch5 GUID <866738B9h,6CF2h,4DE8h,<87h,67h,0F7h,94h,0EBh,0E7h,4Fh,4Eh>>
IID_IShellDispatch6 GUID <286E6F1Bh,7113h,4355h,<95h,62h,96h,0B7h,0E9h,0D6h,4Ch,54h>>


and, the vTables progress like this...
;IUnknown methods (3)

    AddRef
    QueryInterface
    Release

;IDispatch methods (4)

    GetIDsOfNames
    GetTypeInfo
    GetTypeInfoCount
    Invoke

;IShellDispatch properties (2)

    Application
    Parent

;IShellDispatch methods (21)

    NameSpace
    BrowseForFolder
    Windows
    Open
    Explore
    MinimizeAll
    UndoMinimizeALL
    FileRun
    CascadeWindows
    TileVertically
    TileHorizontally
    ShutdownWindows
    Suspend
    EjectPC
    SetTime
    TrayProperties
    Help
    FindFiles
    FindComputer
    RefreshMenu
    ControlPanelItem

;IShellDispatch2 methods (9)

    IsRestricted
    ShellExecute
    FindPrinter
    GetSystemInformation
    ServiceStart
    ServiceStop
    IsServiceRunning
    CanStartStopService
    ShowBrowserBar

;IShellDispatch3 method (1)

    AddToRecent

;IShellDispatch4 methods (4) (visible in XP SP3 without Common Controls 6.0)

    WindowsSecurity
    ToggleDesktop
    ExplorerPolicy
    GetSetting

IShellDispatch5 method (1) (suspect visible with Common Controls 6.0 and/or some level of .NET)

    WindowSwitcher

IShellDispatch6 method (1) (suspect visible with Windows 8 and/or some level of .NET)

    SearchCommand


i'm not really sure what's required to get the later versions
but, it doesn't matter, because we're primarily interested in NameSpace


the other thing i learned today was how to build a C++ program using Visual C++ 2005 Express
not being much on compilers, that's a big step for me   :P
tomorrow, i'll be able to play some more
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 02, 2014, 09:08:37 PM
this works, but it seems like a lot of code   :P
it's a starting point
the empty zip file and folders must exist
int _tmain(int argc, _TCHAR* argv[])
{
    DWORD strlen = 0;
    char szFrom[] = "C:\\ZipTest\\ZipIt",
         szTo[] = "C:\\ZipTest\\New\\New.zip";
    HRESULT hResult;
    IShellDispatch *pISD;
    Folder *pToFolder = NULL;
    VARIANT vDir, vFile, vOpt;
    BSTR strptr1, strptr2;

    CoInitialize(NULL);

    hResult = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void **)&pISD);

    if  (SUCCEEDED(hResult) && pISD != NULL)
    {
        strlen = MultiByteToWideChar(CP_ACP, 0, szTo, -1, 0, 0);
        strptr1 = SysAllocStringLen(0, strlen);
        MultiByteToWideChar(CP_ACP, 0, szTo, -1, strptr1, strlen);

        VariantInit(&vDir);
        vDir.vt = VT_BSTR;
        vDir.bstrVal = strptr1;
        hResult = pISD->NameSpace(vDir, &pToFolder);

        if  (SUCCEEDED(hResult))
        {
            strlen = MultiByteToWideChar(CP_ACP, 0, szFrom, -1, 0, 0);
            strptr2 = SysAllocStringLen(0, strlen);
            MultiByteToWideChar(CP_ACP, 0, szFrom, -1, strptr2, strlen);

            VariantInit(&vFile);
            vFile.vt = VT_BSTR;
            vFile.bstrVal = strptr2;

            VariantInit(&vOpt);
            vOpt.vt = VT_I4;
            vOpt.lVal = 4;          // Do not display a progress dialog box

            hResult = NULL;
            printf("Copying %s to %s ...\n", szFrom, szTo);
            hResult = pToFolder->CopyHere(vFile, vOpt); //NOTE: this appears to always return S_OK even on error
            /*
             * 1) Enumerate current threads in the process using Thread32First/Thread32Next
             * 2) Start the operation
             * 3) Enumerate the threads again
             * 4) Wait for any new threads using WaitForMultipleObjects
             *
             * Of course, if the operation creates any new threads that don't exit, then you have a problem.
             */
                 if (hResult == S_OK) {
                     //NOTE: hard-coded for testing - be sure not to overflow the array if > 5 threads exist
                     HANDLE hThrd[5];
                     HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPALL ,0);  //TH32CS_SNAPMODULE, 0);
                     DWORD NUM_THREADS = 0;
                     if (h != INVALID_HANDLE_VALUE) {
                         THREADENTRY32 te;
                         te.dwSize = sizeof(te);
                         if (Thread32First(h, &te)) {
                             do {
                                 if (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID)) ) {
                                     //only enumerate threads that are called by this process and not the main thread
                                     if((te.th32OwnerProcessID == GetCurrentProcessId()) && (te.th32ThreadID != GetCurrentThreadId()) ){
                                         //printf("Process 0x%04x Thread 0x%04x\n", te.th32OwnerProcessID, te.th32ThreadID);
                                         hThrd[NUM_THREADS] = OpenThread(THREAD_ALL_ACCESS, FALSE, te.th32ThreadID);
                                         NUM_THREADS++;
                                    }
                                }
                                te.dwSize = sizeof(te);
                            } while (Thread32Next(h, &te));
                        }
                        CloseHandle(h);

                        printf("waiting for all threads to exit...\n");
                        //Wait for all threads to exit
                        WaitForMultipleObjects(NUM_THREADS, hThrd , TRUE , INFINITE);

                        //Close All handles
                        for ( DWORD i = 0; i < NUM_THREADS ; i++ ){
                            CloseHandle( hThrd[i] );
                        }
                    } //if invalid handle
                } //if CopyHere() hResult is S_OK

            SysFreeString(strptr2);
            pToFolder->Release();
        }

        SysFreeString(strptr1);
        pISD->Release();
    }

    CoUninitialize();

    printf ("Press ENTER to exit\n");
    getchar();
    return 0;

}


while reading, i came across this function that looked interesting
the descriptions are sometimes misleading, though

SHGetInstanceExplorer
http://msdn.microsoft.com/en-us/library/windows/desktop/bb762186%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/bb762186%28v=vs.85%29.aspx)
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on June 02, 2014, 10:00:31 PM
I think that SHGetInstanceExplorer is called from the shell extension / component's  side .
I didn't know that we can get thread handle from its ID and thus can use WaitForMultipleObjects function.
MSDN (http://msdn.microsoft.com/ru-ru/library/windows/desktop/ms687025(v=vs.85).aspx) has a warning about its usage in Remarks:
QuoteUse caution when calling the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses a wait function with no time-out interval may cause the system to become deadlocked.

CopyHere method doesn't return any value so it's our job to check if the copy operation was successful .

I don't understand this line of code:
Quoteif (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID)) ) {
Could anybody explain its meaning?
Title: Re: Number and type of arguments required for call to C library
Post by: qWord on June 02, 2014, 10:49:26 PM
Quote from: vertograd on June 02, 2014, 10:00:31 PMI don't understand this line of code:
Quoteif (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID)) ) {
Could anybody explain its meaning?
Quote from: msdnThe calling application must set the dwSize member of THREADENTRY32 to the size, in bytes, of the structure. Thread32First (http://msdn.microsoft.com/en-us/library/windows/desktop/ms686728%28v=vs.85%29.aspx) changes dwSize to the number of bytes written to the structure. This will never be greater than the initial value of dwSize, but it may be smaller. If the value is smaller, do not rely on the values of any members whose offsets are greater than this value.
I'm really curious under which conditions the structure is only partially filled, even it seems like some backward compatibility issue...
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on June 02, 2014, 10:55:52 PM
qWord, thank you
Now it makes sense .
Title: Re: Number and type of arguments required for call to C library
Post by: adeyblue on June 03, 2014, 06:11:16 AM
Quote from: qWord on June 02, 2014, 10:49:26 PM
Quote from: msdnThe calling application must set the dwSize member of THREADENTRY32 to the size, in bytes, of the structure. Thread32First (http://msdn.microsoft.com/en-us/library/windows/desktop/ms686728%28v=vs.85%29.aspx) changes dwSize to the number of bytes written to the structure. This will never be greater than the initial value of dwSize, but it may be smaller. If the value is smaller, do not rely on the values of any members whose offsets are greater than this value.
I'm really curious under which conditions the structure is only partially filled, even it seems like some backward compatibility issue...

There are none (so far). The struct has been the same size from Win95 to 8.1, and all the thread funcs do is basically open a memory mapped file and memcpy the relevant struct.

Quote from: dedndave
hResult = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void **)&pISD);
If you don't mind Microsoft's ominous, but so far untrue words (http://msdn.microsoft.com/en-us/library/windows/desktop/bb762124(v=vs.85).aspx) (it still exists and works fine in 8.1). You can skip hitting the registry and all of ole32's funkiness with:

hResult = SHCoCreateInstance(NULL, &CLSID_Shell, NULL, IID_IShellDispatch, (void **)&pISD);
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 03, 2014, 08:59:08 AM
you can create it directly

IFNDEF CLSCTX_INPROC_SERVER
    CLSCTX_INPROC_SERVER EQU 1
ENDIF

        .DATA

CLSID_Shell         GUID <13709620h,0C279h,11CEh,<0A4h,9Eh,44h,45h,53h,54h,0,0>>
IID_IShellDispatch  GUID <0D8F015C0h,0C278h,11CEh,<0A4h,9Eh,44h,45h,53h,54h,0,0>>

        .DATA?

pvShell  LPVOID ?

        .CODE

        INVOKE  CoInitialize,NULL
        INVOKE  CoCreateInstance,offset CLSID_Shell,NULL,CLSCTX_INPROC_SERVER,offset IID_IShellDispatch,offset pvShell
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 03, 2014, 09:04:50 AM
once you have it, you just need some proper vTable structures   :biggrin:

let's start with qWord's METHOD macro

;METHOD macro by qWord

METHOD  MACRO   name,args:VARARG
        LOCAL   _type1,_type2
        _type1  TYPEDEF PROTO args
        _type2  TYPEDEF PTR _type1
        EXITM   <name _type2 ?>
        ENDM


then, IUnknown and IDispatch

;IUnknown interface vTable (structure)

IUnknown STRUCT
  METHOD(QueryInterface, _this:LPVOID,riid:LPVOID,ppvObj:LPVOID)
  METHOD(AddRef,         _this:LPVOID)
  METHOD(Release,        _this:LPVOID)
IUnknown ENDS

;IDispatch interface vTable (structure)

IDispatch STRUCT
    IUnknown                 <>
  METHOD(GetTypeInfoCount, _this:LPVOID,pctinfo:LPVOID)
  METHOD(GetTypeInfo,      _this:LPVOID,iTInfo:UINT,lcid:LCID,ppTInfo:LPVOID)
  METHOD(GetIDsOfNames,    _this:LPVOID,riid:LPVOID,rgszNames:LPOLESTR,cNames:UINT,lcid:LCID,rgDispId:LPVOID)
  METHOD(dInvoke,          _this:LPVOID,dispIdMember:DWORD,riid:LPVOID,lcid:LCID,wFlags:DWORD,pDispParams:LPVOID,pVarResult:LPVOID,pExcepInfo:LPVOID,puArgErr:LPVOID)
IDispatch ENDS


because we created an IShellDispatch interface...

;IShellDispatch interface vTable (structure)
;       vDir VARIANT struct = vtDir:DWORD,vD0:DWORD,vstrDir:LPVOID,vDV0:DWORD
;vRootFolder VARIANT struct = vtRoot:DWORD,vR0:DWORD,vstrRoot:LPVOID,vRV0:DWORD

IShellDispatch STRUCT
    IDispatch                <>
  METHOD(Application,      _this:LPVOID,ppid:LPVOID)
  METHOD(Parent,           _this:LPVOID,ppid:LPVOID)
  METHOD(NameSpace,        _this:LPVOID,vtDir:DWORD,vD0:DWORD,vstrDir:LPVOID,vDV0:DWORD,ppsdf:LPVOID)
  METHOD(BrowseForFolder,  _this:LPVOID,Hwnd:DWORD,lpTitle:LPVOID,Options:DWORD,vtRoot:DWORD,vR0:DWORD,vstrRoot:LPVOID,vRV0:DWORD,ppsdf:LPVOID)
  METHOD(Windows,          _this:LPVOID,ppid:LPVOID)
  METHOD(Open,             _this:LPVOID,vtDir:DWORD,vD0:DWORD,vstrDir:LPVOID,vDV0:DWORD)
  METHOD(Explore,          _this:LPVOID,vtDir:DWORD,vD0:DWORD,vstrDir:LPVOID,vDV0:DWORD)
  METHOD(MinimizeAll,      _this:LPVOID)
  METHOD(UndoMinimizeALL,  _this:LPVOID)
  METHOD(FileRun,          _this:LPVOID)
  METHOD(CascadeWindows,   _this:LPVOID)
  METHOD(TileVertically,   _this:LPVOID)
  METHOD(TileHorizontally, _this:LPVOID)
  METHOD(ShutdownWindows,  _this:LPVOID)
  METHOD(Suspend,          _this:LPVOID)
  METHOD(EjectPC,          _this:LPVOID)
  METHOD(SetTime,          _this:LPVOID)
  METHOD(TrayProperties,   _this:LPVOID)
  METHOD(Help,             _this:LPVOID)
  METHOD(FindFiles,        _this:LPVOID)
  METHOD(FindComputer,     _this:LPVOID)
  METHOD(RefreshMenu,      _this:LPVOID)
  METHOD(ControlPanelItem, _this:LPVOID,bstrDir:LPVOID)
IShellDispatch ENDS


when you call the IShellDispatch::NameSpace method, it returns a "folder object".
the folder object is another IDispatch interface - from which we can call the CopyHere method

;IShellDispatch::NameSpace Folder object interface vTable (structure)
;   vItem VARIANT struct = vtItem:DWORD,vI0:DWORD,vdwItem:DWORD,vIV0:DWORD
;vOptions VARIANT struct = vtOpt:DWORD,vO0:DWORD,vdwOpt:LPVOID,vOV0:DWORD

Folder STRUCT
    IDispatch            <>
  METHOD(getTitle,     _this:LPVOID,pbs:LPVOID)
  METHOD(Application,  _this:LPVOID,ppid:LPVOID)
  METHOD(Parent,       _this:LPVOID,ppid:LPVOID)
  METHOD(ParentFolder, _this:LPVOID,ppsf:LPVOID)
  METHOD(Items,        _this:LPVOID,ppid:LPVOID)
  METHOD(ParseName,    _this:LPVOID,bstrName:LPVOID,ppid:LPVOID)
  METHOD(NewFolder,    _this:LPVOID,bstrName:LPVOID,vtOpt:DWORD,vO0:DWORD,vdwOpt:LPVOID,vOV0:DWORD)
  METHOD(MoveHere,     _this:LPVOID,vtItem:DWORD,vI0:DWORD,vdwItem:DWORD,vIV0:DWORD,vtOpt:DWORD,vO0:DWORD,vdwOpt:LPVOID,vOV0:DWORD)
  METHOD(CopyHere,     _this:LPVOID,vtItem:DWORD,vI0:DWORD,vdwItem:DWORD,vIV0:DWORD,vtOpt:DWORD,vO0:DWORD,vdwOpt:LPVOID,vOV0:DWORD)
  METHOD(GetDetailsOf, _this:LPVOID,vtItem:DWORD,vI0:DWORD,vdwItem:DWORD,vIV0:DWORD,iColumn:DWORD,pbs:LPVOID)
Folder ENDS


now that we have proper vTable definitions, we just need a little work with VARIANT structures,
and, of course, a way to know when it's done zipping   :t

i was having a hard time figuring out how to call the NameSpace and CopyHere methods
now that i have those figured out, things should get a little easier   :biggrin:

EDIT: updated IShellDispatch and Folder vTable structures to allow VARIANT's as DWORD's
EDIT: modified "Title" to "getTitle" in Folder vTable to avoid use of reserved keyword
modified "Title" to "lpTitle" in IShellDispatch, BrowseForFolder arguments - same reason
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 03, 2014, 10:57:11 AM
reports all over the web say that "CopyHere options don't work"
probably because they are passing the flags directly as an integer
it's a pointer to a VT_I4 VARIANT structure   :biggrin:
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on June 03, 2014, 05:27:42 PM
Quote from: dedndave on June 03, 2014, 10:57:11 AM
reports all over the web say that "CopyHere options don't work"
...
http://msdn.microsoft.com/en-us/library/windows/desktop/bb787866(v=vs.85).aspx:
QuoteNote  In some cases, such as compressed (.zip) files, some option flags may be ignored by design.
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 03, 2014, 07:18:27 PM
these seem to be pertinent for zipping files/folders
there may be more

(content removed, see next post)
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 03, 2014, 09:01:49 PM
added a couple more
IFNDEF FOF_SILENT
  FOF_SILENT            EQU 4     ;Do not display a progress dialog box.
ENDIF

IFNDEF FOF_RENAMEONCOLLISION
  FOF_RENAMEONCOLLISION EQU 8     ;Give the file being operated on a new name if a file with the target name already exists.
ENDIF

IFNDEF FOF_NOCONFIRMATION
  FOF_NOCONFIRMATION    EQU 10h   ;Respond with "Yes to All" for any dialog box that is displayed.
ENDIF

IFNDEF FOF_SIMPLEPROGRESS
  FOF_SIMPLEPROGRESS    EQU 100h  ;Display a progress dialog box but do not show the file names.
ENDIF

IFNDEF FOF_NOCONFIRMMKDIR
  FOF_NOCONFIRMMKDIR    EQU 200h  ;Do not confirm the creation of a new directory if the operation requires one to be created.
ENDIF

IFNDEF FOF_NOERRORUI
  FOF_NOERRORUI         EQU 400h  ;Do not display a user interface if an error occurs.
ENDIF
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 04, 2014, 12:50:05 AM
ok - big mistake on my part
a pointer to the VARIANT structure is not passed
the entire VARIANT structure is passed
no wonder it looked so confusing   :redface:

i will have to update my interface vTable structures
for asm code, it's best to define it as dwords, so it will take a little work
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 04, 2014, 02:56:26 AM
updated the IShellDispatch and Folder vTable structures in Reply #103

now, we are ready to rock and roll   :biggrin:

no wonder everything kept crashing
the stack was probably out of balance
we PUSH'ed too few parms (the worst kind of imbalance)
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 04, 2014, 04:29:21 AM
it works - and it zips the files
i just have to figure out why my UNICODE aware hex routine is adding an extra space   :lol:
then, i'll post an EXE with source
                     Stack Pointer:  0012FFC4
                  CoCreateInstance: Success
IShellDispatch::NameSpace(Target): Success
          Folder::CopyHere(Source): (no return value)
                   Folder::Release: Success
           IShellDispatch::Release: Success
                     Stack Pointer:  0012FFC4

Press any key to continue ...
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 04, 2014, 04:53:52 AM
doh !
i forgot the -1   :biggrin:
    INVOKE  awConOut,lengthof sz0000-1,offset sz0000

here it is.....
you will have to create a folder structure
  C:\ZipTest
      \New
      \ZipIt
          Test1.txt
          \Test
              Test2.txt

Test1.txt and Test2.txt are small text files
you can put whatever you like into the ZipIt folder
but, i am only using a 5 second delay to let it finish
the resulting ZIP file will be C:\ZipTest\New\New.zip

now, i can work on detecting when it's done

by the way - it builds and runs as UNICODE or ANSI

EDIT: changed some UNICODE Aware stuff - no functional changes
EDIT: more uneventful UNICODE Aware updates
Title: Re: Number and type of arguments required for call to C library
Post by: adeyblue on June 04, 2014, 06:27:52 AM
Since peter_asm posted an example of finding the thread and waiting for it, here's a version that uses the shell notifications:

#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <shldisp.h>
#include <shlobj.h>
#include <ole2.h>
#include <cstdio>

#define CHECK_FAIL(x) \
    { \
        HRESULT hr = (x); \
        if(FAILED(hr)) \
        { \
            printf(#x " failed with error %#x\n", hr); \
            goto exit; \
        } \
    }

const UINT g_zipFinMsg = WM_APP + 0x50;

LRESULT __stdcall ZipWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static HANDLE hExitHandle = NULL;
    switch(msg)
    {
        case WM_CREATE:
        {
            LPCREATESTRUCT pCS = reinterpret_cast<LPCREATESTRUCT>(lParam);
            hExitHandle = static_cast<HANDLE>(pCS->lpCreateParams);
        }
        break;
        case g_zipFinMsg:
        {
            SetEvent(hExitHandle);
            DestroyWindow(hwnd);
        }
        break;
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

void CreateZipFile(PCWSTR pZip)
{
    CloseHandle(CreateFile(pZip, STANDARD_RIGHTS_WRITE, 0, NULL, OPEN_ALWAYS, 0x80, NULL));
}

HWND CreateZipWaitWnd(HANDLE hEvent)
{
    WNDCLASSEX wndClass = {sizeof(wndClass), 0};
    wndClass.lpfnWndProc = &ZipWndProc;
    wndClass.hInstance = GetModuleHandle(NULL);
    wndClass.lpszClassName = L"ZipWnd";
    RegisterClassEx(&wndClass);
    return CreateWindowEx(
        0,
        wndClass.lpszClassName,
        L"",
        WS_OVERLAPPEDWINDOW,
        1,
        1,
        1,
        1,
        HWND_MESSAGE,
        NULL,
        wndClass.hInstance,
        hEvent
    );
}

BSTR GetFullZipPath(PCWSTR pZip)
{
    DWORD charsReq = GetFullPathName(pZip, 0, NULL, 0);
    BSTR zipPath = SysAllocStringLen(NULL, charsReq);
    GetFullPathName(pZip, charsReq, zipPath, NULL);
    return zipPath;
}

void ScriptyZip(PCWSTR pZip, PCWSTR pItemsToZip)
{
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

    IShellDispatch* pShellDisp = NULL;
    Folder* pZipFolder = NULL, *pOutFolder = NULL;
    FolderItems* pThingsToZip = NULL;

    BSTR zipFile = GetFullZipPath(pZip);
    CreateZipFile(zipFile);
    BSTR outputDir = SysAllocString(pItemsToZip);

    VARIANT varZip = {VT_BSTR}; varZip.bstrVal = zipFile;
    VARIANT varOutDir = {VT_BSTR}; varOutDir.bstrVal = outputDir;
    VARIANT varDispItems = {VT_DISPATCH};
    VARIANT varCopyOpts = {VT_UI4};

    HRESULT hRes = SHCoCreateInstance(NULL, &CLSID_Shell, NULL, IID_IShellDispatch, (void**)&pShellDisp);
    // Folder object for the zip file
    CHECK_FAIL(pShellDisp->NameSpace(varZip, &pZipFolder));
    // Folder object for the output folder
    CHECK_FAIL(pShellDisp->NameSpace(varOutDir, &pOutFolder));
    // Get the items in the folder
    CHECK_FAIL(pOutFolder->Items(&pThingsToZip));

    varDispItems.pdispVal = pThingsToZip;

    // create the window and setup the shell notification before
    // CopyHere so we can catch even the quickest of operations
    HANDLE hExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    HWND hwndWaitWindow = CreateZipWaitWnd(hExitEvent);
    if(!(hExitEvent && hwndWaitWindow))
    {
        goto exit;
    }
    SHChangeNotifyEntry entry = {ILCreateFromPath(pZip), FALSE};
    ULONG regId = SHChangeNotifyRegister(
        hwndWaitWindow,
        SHCNRF_InterruptLevel | SHCNRF_ShellLevel,
        SHCNE_CREATE | SHCNE_UPDATEITEM,
        g_zipFinMsg,
        1,
        &entry
    );
    pZipFolder->CopyHere(varDispItems, varCopyOpts);
    DWORD ret;
    while((ret = MsgWaitForMultipleObjects(1, &hExitEvent, FALSE, INFINITE, QS_ALLINPUT)) <= 1)
    {
        // exit event set
        if(ret == 0)
        {
            break;
        }
        // message received
        else
        {
            MSG msg;
            while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            {
                DispatchMessage(&msg); // don't need TranslateMessage
            }
        }
    }
    SHChangeNotifyDeregister(regId);
    ILFree((LPITEMIDLIST)entry.pidl);

exit:
    if(hExitEvent)
    {
        CloseHandle(hExitEvent);
    }
    if(pThingsToZip)
    {
        pThingsToZip->Release();
    }
    if(pZipFolder)
    {
        pZipFolder->Release();
    }
    if(pOutFolder)
    {
        pOutFolder->Release();
    }
    if(pShellDisp)
    {
        pShellDisp->Release();
    }
    SysFreeString(zipFile);
    SysFreeString(outputDir);
    CoUninitialize();
}

int wmain(int argc, wchar_t** argv)
{
    if(argc != 3)
    {
        return puts("Usage: ScriptyZip file.zip c:\\dir\\or\\file\\to.add");
    }
    else
    {
        ScriptyZip(argv[1], argv[2]);
    }
    return 0;
}
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 04, 2014, 12:30:28 PM
updated the attachment in Reply #111
Title: Re: Number and type of arguments required for call to C library
Post by: Gunther on June 04, 2014, 04:32:02 PM
Quote from: dedndave on June 04, 2014, 12:30:28 PM
updated the attachment in Reply #111

:t

Gunther
Title: Re: Number and type of arguments required for call to C library
Post by: jj2007 on June 04, 2014, 04:36:39 PM
Quote from: dedndave on June 04, 2014, 12:30:28 PM
updated the attachment in Reply #111

Win7-32: Creates New.zip at 22 bytes (after pointing bstrPathTarget and szZipFile to existing folders) but fails for IShellDispatch.NameSpace :(

So it works for you, Gunther?

@adeyblue: pShellDisp->NameSpace(varOutDir, &pOutFolder) failed with error 0x80004005 :(
Title: Re: Number and type of arguments required for call to C library
Post by: Gunther on June 04, 2014, 05:29:26 PM
Jochen,

Quote from: jj2007 on June 04, 2014, 04:36:39 PM
So it works for you, Gunther?

at least with my old XP box.

                     Stack Pointer: 0013FFC4
                  CoCreateInstance: Success
IShellDispatch::NameSpace(Target): 00000001
           IShellDispatch::Release: Success
                     Stack Pointer: 0013FFC4

Press any key to continue...


I can test it with Win7-64 not before Friday, because I'm currently on the island of Rügen (with bad internet access :().

Gunther 
Title: Re: Number and type of arguments required for call to C library
Post by: sinsi on June 04, 2014, 06:06:00 PM
Working here (after a change - hard coded paths dave?), creates a 791KB new.zip
Windows 8.1 Pro x64


                     Stack Pointer: 0018FF90
                  CoCreateInstance: Success
IShellDispatch::NameSpace(Target): Success
          Folder::CopyHere(Source): (no return value)
                   Folder::Release: Success
           IShellDispatch::Release: Success
                     Stack Pointer: 0018FF90

Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on June 04, 2014, 09:48:53 PM
Dave,
Did you test CopyHere's option flags ?
I'm curious which of them work for zip folders.
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 04, 2014, 10:53:49 PM
no - i didn't test them yet
but - i zipped the contents of masm32\include (longer time delay), and with the current flagset - no progress dialog, as desired

as for the hard-coded paths, yes
i wanted to spend time figuring out how the COM stuff worked
not spend time writing a fancy program - lol

the way it's written, you create the following folders
C:\ZipTest
C:\ZipTest\New
C:\ZipTest\ZipIt

the stuff you put into the ZipIt folder will be zipped
so, for test purposes, i put a text file, and a folder containing a text file into the ZipIt folder
Title: Re: Number and type of arguments required for call to C library
Post by: Gunther on June 05, 2014, 02:41:46 AM
Quote from: dedndave on June 04, 2014, 10:53:49 PM
the stuff you put into the ZipIt folder will be zipped
so, for test purposes, i put a text file, and a folder containing a text file into the ZipIt folder

That makes things a bit clearer.

Gunther
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 05, 2014, 03:15:10 AM
sorry - i made a mistake on that last attachment

  UCSTR   bstrPathSource, "C:\masm32\include",0 ;"C:\ZipTest\ZipIt",0

for testing, i zipped the contents of the include folder
but, i forgot to remove the test string   :(

  UCSTR   bstrPathSource, "C:\ZipTest\ZipIt",0

so, the ISDZip4.zip update fixes that issue (Reply #111)
Title: Re: Number and type of arguments required for call to C library
Post by: jj2007 on June 05, 2014, 08:28:38 AM
Reply #111 still doesn't work for me, the NameSpace thingy fails :(
I also don't see the compressed folder option when I right-click on a file; regsvr32 zipfldr.dll didn't help (yes, I rebooted).

I'd love to have a 3rd party independent zipper. Unzipping works like a charm now with a wrapper for Jørgen Ibsen's tiny inflate (tinf) library (http://www.ibsensoftware.com/download.html):

include \masm32\MasmBasic\MasmBasic.inc      ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  SetCpUtf8            ; filenames in zipfiles are UTF-8 encoded, so we force codepage UTF-8
  Print "*** Attention: Your console may not be able to display all Unicode file names correctly ***", CrLf$, CrLf$
  Print cStyle$("#\tSize\tDate\t\tTime\tFilename\n")
  UnzipInit "\Masm32\MasmBasic\Res\UnicodeTest.zip"
  ; UnzipInit returns a comment or an empty string in eax, the #files in edx, and the Sign? flag to signal an error
  .if Sign?
      Print eax      ; if the sign flag is set, eax points to an error message
  .else
      push eax      ; save the comment returned by UnzipInit
      For_ ecx=0 To edx-1
            PrintLine Str$(ecx+1), Tb$, Str$(GfSize(ecx)), Tb$, GfDate$(ecx), Spc2$, GfTime$(ecx), Tb$, Files$(ecx)
      Next
      pop eax
      PrintLine "Zipfile comment:", CrLf$, eax
      .While 1
            Inkey At(0, 15) "Enter the number of the file you want to see, or Escape to exit", CrLf$, CrLf$, "File #: ", Space$(40)
            .Break .if eax==VK_ESCAPE
            lea ecx, [eax-"1"]
            .if ecx<=Files$(?)
                  Locate(10, 17)
                  Print " ", Files$(ecx)       ; erase rest of previous filename
                  FileWrite Files$(ecx), UnzipFile(ecx), GfLastWrite(ecx)      ; restore the file, and don't forget the timestamp
                  Launch Cat$("..\RichMasm.exe "+Files$(ecx)+"#UTF")
            .endif
      .Endw
      UnzipExit      ; cleanup
  .endif
  Exit
end start


One hilarious thing is that you need at least two archivers to do simple things like adding files or comments:
- 7-Zip to add and delete files
- WinZip to add comments
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 05, 2014, 12:26:39 PM
it seems like unzipping is by far the more difficult task
there are so many different flavours of zip files   :redface:
Title: Re: Number and type of arguments required for call to C library
Post by: Gunther on June 05, 2014, 04:23:27 PM
Quote from: dedndave on June 05, 2014, 12:26:39 PM
it seems like unzipping is by far the more difficult task
there are so many different flavours of zip files   :redface:

yes, indeed. There are historical reasons for that. One reason is the Welch patent.

Gunther
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 05, 2014, 08:26:07 PM
yah - and, it has evolved over about 30 years - lol

the unzip algorithm is probably very simple, compared to the zip algo
Title: Re: Number and type of arguments required for call to C library
Post by: MichaelW on June 06, 2014, 05:06:26 AM
Quote from: Gunther on June 05, 2014, 04:23:27 PM
One reason is the Welch patent.

Shouldn't that be "was the Welch patent"?
Title: Re: Number and type of arguments required for call to C library
Post by: Gunther on June 06, 2014, 05:21:46 AM
Michael,

Quote from: MichaelW on June 06, 2014, 05:06:26 AM
Shouldn't that be "was the Welch patent"?

yes, of course. It's history now, but it wasn't during the 90s.

Gunther
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 06, 2014, 05:55:42 AM
we have been trying to mimic the drag-n-drop method (i guess it's a drop target)
maybe we want to mimic the Send To shell extension, instead
although - that won't give us any control over the dialogs that may appear
it may give us insight as to the "right" way to know when the copy is done

the file lock method that i mentioned earlier may not work very well
at this point, the thread method seems best - but doesn't seem ideal, either
Title: Re: Number and type of arguments required for call to C library
Post by: adeyblue on June 06, 2014, 06:26:02 AM
Quote from: jj2007 on June 04, 2014, 04:36:39 PM
@adeyblue: pShellDisp->NameSpace(varOutDir, &pOutFolder) failed with error 0x80004005 :(

Strange. I'm sure I tried it and it worked before I posted it. But trying it just now and it doesn't just not work, none of the functions fail, and it just straight up crashes. Anyway, I've updated it and tried it and fingers crossed it's good to go now (on Win7 x64).

EDIT: Or not. Argh! Seems MS don't want you using pidls in VARIANT's. In XP the type Namespace() wants is VT_ARRAY | VT_UI1, in 7 that's changed to VT_VECTOR | VT_UI1. Just to make matters worse, 7 has reused VT_ARRAY | VT_UI1 to mean a completely different structure. So I'll go revert the code back to using names.

Quote from: dedndave on June 06, 2014, 05:55:42 AM
we have been trying to mimic the drag-n-drop method (i guess it's a drop target)
maybe we want to mimic the Send To shell extension, instead
Do you shoot messengers around here? Send To is yet another wrapper around drag & drop (http://i.imgur.com/Q5PelXT.png), at least in the case of zipfldr.
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on June 06, 2014, 07:14:02 AM
Quote from: dedndave on June 06, 2014, 05:55:42 AM
we have been trying to mimic the drag-n-drop method (i guess it's a drop target)
...
I think that it was adeyblue who has been trying to mimic the drag-n-drop method in his article.
We were using top level scriptable shell interfaces and two their methods: NameSpace and CopyHere.
The main problem was to wait for shell's threads termination . I've never debugged multythreaded applications  before .  It was an exciting quest .

Quote from: dedndave on June 06, 2014, 05:55:42 AM
...
maybe we want to mimic the Send To shell extension, instead
...
Sure ! A day or two ago I was playing with powershell  thinking about this method .
So here's the sequence of actions  in short:
creating Shell object -> NameSpace("C:\ZIPIT") ->ParseName("test.asm") -> now that we have IFolderItem object for out test file   we want to see its Verbs -> IFolderItem ::Verbs -> now I dumped the result (count of verbs =15) ,there were all those items that you see when cklicking RMB  ... EXCEPT Send To ... (I remember it was #8 - an empty line )  .
Problem #1: how to find Send To submenu of the context menu and parse its options
Problem #2: what if there's no "Zip folder" option in the "Send to"  submenu ? Should we register it ? How?   

Also I was thinking about creating custom drop target like that empty file on the desktop with .zfSendToTraget  extension which zips everything that you drag'n'drop on it . 



Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 06, 2014, 08:18:46 AM
i don't think our "final" solution will be to use the Send To mechanism
however, we might be able to gain some insight from watching it   :P
that takes care of problem #2

problem #1 is a little tricky
but, we should be able to follow the chain through the registry
a couple ways come to mind:
1) dredge through the registry chain
2) pretend we want to write a Send To shell extension and see how it works - lol

one of the zipfldr.dll resources is an INF file that registers it
[Version]
Signature="$CHICAGO$"
[RegAlways]
AddReg=ZipFldr.RegAlways
DelReg=Delete.RegAlways
RequiredEngine=SETUPAPI,%ERR_NOSETUPAPI%
[RegTakeDefault]
AddReg=ZipFldr.RegTakeDefault
DelReg=Delete.RegTakeDefault
RequiredEngine=SETUPAPI,%ERR_NOSETUPAPI%
[Unreg]
DelReg=ZipFldr.RegAlways,ZipFldr.RegTakeDefault
[ZipFldr.RegTakeDefault]
HKCR,.zip,,,CompressedFolder
HKCR,.zip,"Content Type",,"application/x-zip-compressed"
[Delete.RegTakeDefault]
[ZipFldr.RegAlways]
HKCR,CLSID\%CLSID_ZIPFLD%,,,CompressedFolder
HKCR,CLSID\%CLSID_ZIPFLD%\DefaultIcon,,%REGEXSZ%,%_SYS_MOD_PATH%
HKCR,CLSID\%CLSID_ZIPFLD%\InProcServer32,,%REGEXSZ%,%_SYS_MOD_PATH%
HKCR,CLSID\%CLSID_ZIPFLD%\InProcServer32,ThreadingModel,,Apartment
HKCR,CLSID\%CLSID_ZIPFLD%\ProgID,,,CompressedFolder
HKCR,CLSID\%CLSID_ZIPFLD%\ShellFolder,Attributes,%REGDW%,0x200001a0
HKCR,CLSID\%CLSID_ZIPFLD%\ShellFolder,UseDropHandler,,
HKCR,.zip\OpenWithProgids,CompressedFolder
HKCR,.zip\CompressedFolder\ShellNew,Data,%REGBINARY%,50,4B,05,06,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
HKCR,"Applications\zipfldr.dll",NoOpenWith,,
HKCR,CompressedFolder,,,"%COMPRESSED_FOLDER%"
HKCR,CompressedFolder,"FriendlyTypeName",%REGEXSZ%,"@%_SYS_MOD_PATH%,-10195"
HKCR,CompressedFolder\CLSID,,,%CLSID_ZIPFLD%
HKCR,"SystemFileAssociations\.zip\CLSID",,,%CLSID_ZIPFLD%
HKCR,CompressedFolder\DefaultIcon,,%REGEXSZ%,%_SYS_MOD_PATH%
HKCR,CompressedFolder\Shell\Open\Command,,,"rundll32.exe zipfldr.dll,RouteTheCall %%L"
HKCR,"CompressedFolder\shell\open",BrowserFlags,%REGDW%,0x0010
HKCR,"CompressedFolder\shell\open",ExplorerFlags,%REGDW%,0x0012
HKCR,CompressedFolder\Shell\Open\ddeexec,,,"[ViewFolder(""%%l"", %%I, %%S)]"
HKCR,CompressedFolder\Shell\Open\ddeexec,NoActivateHandler
HKCR,CompressedFolder\Shell\Open\ddeexec\application,,,"Folders"
HKCR,CompressedFolder\Shell\Open\ddeexec\ifexec,,,"[]"
HKCR,CompressedFolder\Shell\Open\ddeexec\topic,,,"AppProperties"
HKCR,CompressedFolder\shell\find,SuppressionPolicy,%REGDW%,0x00000080
HKCR,CompressedFolder\shell\find\command,,%REGEXSZ%,"%25%\Explorer.exe"
HKCR,CompressedFolder\shell\find\ddeexec,,,"[FindFolder(""%l"", %I)]"
HKCR,CompressedFolder\shell\find\ddeexec\application,,,"Folders"
HKCR,CompressedFolder\shell\find\ddeexec\topic,,,"AppProperties"
HKCR,CompressedFolder\ShellEx\ContextMenuHandlers\%CLSID_ZIPCONTEXTMENU%,,,"Compressed (zipped) Folder Menu"
HKCR,CompressedFolder\ShellEx\DropHandler,,,"%CLSID_ZipFolderDropHandler%"
HKCR,CompressedFolder\ShellEx\StorageHandler,,,"%CLSID_ZIPFLD%"
HKCR,MIME\Database\Content Type\application/x-zip-compressed,"Extension",,".zip"
HKCR,CLSID\%CLSID_ZIPDRAG%,,,"Compressed (zipped) Folder Right Drag Handler"
HKCR,CLSID\%CLSID_ZIPDRAG%\InProcServer32,,%REGEXSZ%,%_SYS_MOD_PATH%
HKCR,CLSID\%CLSID_ZIPDRAG%\InProcServer32,"ThreadingModel",,"Apartment"
HKCR,Folder\shellex\DragDropHandlers\%CLSID_ZIPDRAG%
HKCR,CLSID\%CLSID_ZIPSENDTO%,,,"Compressed (zipped) Folder SendTo Target"
HKCR,CLSID\%CLSID_ZIPSENDTO%,"FriendlyTypeName",%REGEXSZ%,"@%_SYS_MOD_PATH%,-10226"
HKCR,CLSID\%CLSID_ZIPSENDTO%\InProcServer32,,%REGEXSZ%,%_SYS_MOD_PATH%
HKCR,CLSID\%CLSID_ZIPSENDTO%\InProcServer32,"ThreadingModel",,"Apartment"
HKCR,CLSID\%CLSID_ZIPSENDTO%\DefaultIcon,,%REGEXSZ%,%_SYS_MOD_PATH%
HKCR,CLSID\%CLSID_ZIPSENDTO%\ShellEx\DropHandler,,,"%CLSID_ZIPSENDTO%"
HKCR,CLSID\%CLSID_ZIPSENDTO%,NeverShowExt
HKCR,CLSID\%CLSID_ZIPSENDTO%,NoOpen,,"%NOOPEN%"
HKCR,CLSID\%CLSID_ZIPSENDTO%,EditFlags,%REGDW%,0x00000001
HKCR,CLSID\%CLSID_ZIPCONTEXTMENU%,,,"Compressed (zipped) Folder Context Menu"
HKCR,CLSID\%CLSID_ZIPCONTEXTMENU%\InProcServer32,,%REGEXSZ%,%_SYS_MOD_PATH%
HKCR,CLSID\%CLSID_ZIPCONTEXTMENU%\InProcServer32,"ThreadingModel",,"Apartment"
HKCR,CLSID\%CLSID_ZipFolderDropHandler%,,,"Compressed (zipped) Folder DropHandler"
HKCR,CLSID\%CLSID_ZipFolderDropHandler%\InProcServer32,,%REGEXSZ%,%_SYS_MOD_PATH%
HKCR,CLSID\%CLSID_ZipFolderDropHandler%\InProcServer32,"ThreadingModel",,"Apartment"
HKCR,.ZFSendToTarget,,,CLSID\%CLSID_ZIPSENDTO%
HKLM,"Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved",%CLSID_ZIPFLD%,,"%COMPRESSED_FOLDER%"
HKLM,"Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved",%CLSID_ZIPDRAG%,,"Compressed (zipped) Folder Right Drag Handler"
HKLM,"Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved",%CLSID_ZIPSENDTO%,,"Compressed (zipped) Folder SendTo Target"
[Delete.RegAlways]
HKCR,CLSID\%CLSID_ZIPFLD%\shellex\ExtShellFolderViews
HKCR,CompressedFolder\ShellEx\ContextMenuHandlers\%CLSID_ZIPFLD%
HKCR,CompressedFolder\Shell\Explore
[Strings]
REGDW=0x00010001
REGEXSZ=0x00020000
REGBINARY=0x00000001
CLSID_ZIPFLD={E88DCCE0-B7B3-11d1-A9F0-00AA0060FA31}
CLSID_ZIPDRAG={BD472F60-27FA-11cf-B8B4-444553540000}
CLSID_ZIPSENDTO={888DCA60-FC0A-11CF-8F0F-00C04FD7D062}
CLSID_ZIPCONTEXTMENU={b8cdcb65-b1bf-4b42-9428-1dfdb7ee92af}
CLSID_ZipFolderDropHandler={ed9d80b9-d157-457b-9192-0e7280313bf0}
COMPRESSED_FOLDER = "Compressed (zipped) Folder"
NOOPEN="Drag Files onto this icon to compress them."
ERR_NOSETUPAPI="Can not register ZIPFLDR.DLL because SETUPAPI.DLL is missing."
[End]


looking at the code, it seems that it creates a COM interface
it would take some time to wade through it
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on June 06, 2014, 10:31:23 PM
I'm totally agree
Below I bookmarked several msdn Shell references for further reading
Shell Developer's Guide (//http://)
Working with Shell Extensions (http://msdn.microsoft.com/en-us/library/windows/desktop/ff468984(v=vs.85).aspx)
Creating Shell Extension Handlers (http://msdn.microsoft.com/en-us/library/windows/desktop/cc144067(v=vs.85).aspx)
Registering Shell Extension Handlers (http://msdn.microsoft.com/en-us/library/windows/desktop/cc144110(v=vs.85).aspx)

Well , adding "Compressed (zipped) folder"  option to "Send to" submenu is not very complicated task:
How to Restore Missing "Compressed (zipped) Folder" Item in Send To Menu in Windows XP, ... (http://www.askvg.com/how-to-restore-missing-compressed-zipped-folder-item-in-send-to-menu-in-windows-xp-and-vista/)
Edit the Windows 7 "Send To" Menu Without Third-Party Tools (http://lifehacker.com/5640841/edit-the-windows-7-send-to-menu-without-third-party-tools)
KB310270 (http://support.microsoft.com/kb/310270)

Next,
all we need to check if "Compressed (zipped) folder"  exists in "Send to" submenu is the list of Send to folder's items . We don't even  have to know the full path to it .
Shell special folder ID for "Send to " = 9 (see here (http://masm32.com/board/index.php?topic=2845.0) ) ... so we just call
QuoteIDispatch::NameSpace(9)
and get required folder object .



Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 06, 2014, 11:47:58 PM
QuoteIDispatch::NameSpace(9)

that just opens the SendTo target folder   :P

a few interesting ordinals...

OLEAUT32.2    SysAllocString
OLEAUT32.8    VariantInit
OLEAUT32.9    VariantClear
OLEAUT32.17   SafeArrayGetDim
OLEAUT32.19   SafeArrayGetUBound
OLEAUT32.20   SafeArrayGetLBound
OLEAUT32.23   SafeArrayAccessData
OLEAUT32.24   SafeArrayUnaccessData
OLEAUT32.184  SystemTimeToVariantTime
OLEAUT32.411  SafeArrayCreateVector

SHELL32.16    ILFindLastID
SHELL32.17    ILRemoveLastID
SHELL32.18    ILClone
SHELL32.25    ILCombine
SHELL32.28    SHILCreateFromPath
SHELL32.67    Shell_MergeMenus
SHELL32.73    SHShellFolderView_Message
SHELL32.155   ILFree
SHELL32.165   SHCreateDirectory
SHELL32.182   ShellMessageBoxW
SHELL32.190   ILCreateFromPathW
SHELL32.256   SHCreateShellFolderView
SHELL32.743   SHCreateFileExtractIconW
SHELL32.744   Create_IEnumUICommand
SHELL32.745   Create_IUIElement

SHLWAPI.16    SHCreateThread
SHLWAPI.107   LoadStringWrapW, wrapper for LoadString
SHLWAPI.199   IUnknown_Set
SHLWAPI.215   SHAnsiToUnicode
SHLWAPI.217   SHUnicodeToAnsi
SHLWAPI.219   QISearch
SHLWAPI.346   SHUnicodeToUnicode
SHLWAPI.354   SHFormatDateTimeW
SHLWAPI.456   PathIsValidCharW
SHLWAPI.485   MapWin32ErrorToSTG
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 06, 2014, 11:49:14 PM
hmmmm....

try creating a file with the extension ".ZFSendToTarget" and writing to it
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on June 08, 2014, 07:33:25 PM
Next item to my TODO list:
I'll try the code from this brilliant article (http://blogs.msdn.com/b/oldnewthing/archive/2008/07/24/8768095.aspx) with zip folders as a target  .
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 08, 2014, 09:27:40 PM
yes, Raymond Chen is always a good read

part two...

http://blogs.msdn.com/b/oldnewthing/archive/2008/07/25/8770548.aspx (http://blogs.msdn.com/b/oldnewthing/archive/2008/07/25/8770548.aspx)

QuoteSHSetInstanceExplorer
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on June 08, 2014, 10:16:52 PM
Well , as it always happens - in order to find right solution we must take a pause till the spontaneous insight  :t
Part two contains reference to
Reading a contract from the other side: SHSetInstanceExplorer and SHGetInstanceExplorer (http://blogs.msdn.com/b/oldnewthing/archive/2008/05/28/8555658.aspx) article .

Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 08, 2014, 10:23:19 PM
yes - i was just reading that one   :biggrin:
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on June 08, 2014, 10:26:52 PM
Sad to say but I cannot try it immediately in MS VS and under the debugger 
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 08, 2014, 11:28:01 PM
you're not missing any fun

QuoteIt seems that zipfldr.dll does not call SHGetInstanceExplorer despite creating worker threads.
This may be a bug in zipfldr.dll.

my guess is that it's not a bug
rather, a more involved method is used
but - this may give me a clue where to look
i can look at the thread code in zipfldr.dll
Title: Re: Number and type of arguments required for call to C library
Post by: GoneFishing on June 09, 2014, 02:30:26 AM
I found the origin of the quote :manipulating zipfldr.dll to create a Compressed folder (http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/d3e347cc-f4dc-44a6-8f84-977f958d89c6/manipulating-zipfldrdll-to-create-a-compressed-folder?forum=windowsgeneraldevelopmentissues)
no doubt that it's not a bug
I'll look into the zipfldr's thread too
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 09, 2014, 05:14:25 AM
i tried watching the reference count 3 ways:
IID_IShellDispatch
IID_Folder
IID_FolderItems

no luck on any of that

i have seen several examples where they look at Items.Count
that's probably a good method about 99.9% of the time - lol
just because the count is correct does not mean the last item was completely zipped and added
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 09, 2014, 05:17:18 AM
the Items.Count method would be reliable if we added a "bogey" item to the list
if we could be sure it was the last item to be added, we would know all the other items were complete

seems like a hack, but a good one   :biggrin:
Title: Re: Number and type of arguments required for call to C library
Post by: adeyblue on June 09, 2014, 12:10:29 PM
Went back and looked at the 'doesn't use a separate thread' IStorage method, swapped one hack for another and success! Single thread zipping - with subfolders.

Except, it doesn't work on XP. And you can't have two files anywhere in the zip with the same filename (zipfldr helpfully decides that temporary files it's completely done with should be read-only), and I'm sure there's something else I've forgotten.

So yeah, quite a lot of restrictions unless another mass of zipfldr owned hoops are jumped through. If nothing else it's an example of how to loop through directories and copy them somewhere else with the shell interfaces.
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 09, 2014, 01:15:13 PM
 :t

still, nice to have an IStream example - useful for other things, too
Title: Re: Number and type of arguments required for call to C library
Post by: Gunther on June 09, 2014, 07:36:09 PM
Dave,

Quote from: dedndave on June 08, 2014, 09:27:40 PM
yes, Raymond Chen is always a good read

who is Raymond Chen?

Gunther
Title: Re: Number and type of arguments required for call to C library
Post by: sinsi on June 09, 2014, 07:49:44 PM
http://blogs.msdn.com/b/oldnewthing/
Title: Re: Number and type of arguments required for call to C library
Post by: dedndave on June 09, 2014, 10:52:03 PM
Raymond Chen is a MS programmer, that often blogs about code (see Sinsi's link)
he usually has a pretty good grasp on the code
and - i always learn by reading from the comments section, too
the same is true on CodeProject - the comments are a must-read
Title: Re: Number and type of arguments required for call to C library
Post by: Gunther on June 09, 2014, 11:37:59 PM
Dave, Sinsi,

thank you for that information.  :t

Gunther