How Can I get "E:\NC1020IDE\" from "E:\NC1020IDE\packer.exe"?
Sometimes can seek backward of FullFileName for \ ....
But,is there some API or function for it?
I Delphi,I always use extractfilepath to do it.
thx
Posted on 2002-10-21 07:50:26 by Const.Ex
It is easy to code your own function to do that...

Easy solution (not the fastest, but all depends of the speed of your strlen function).

- call an strlen function (lstrlen)
- search backwards for the '\' character
- put a NULL where it is found...

A bit more complex solution:

- byte scan your string...
- preserve the index of the last '\' to have been found...
- if NULL, you are at the end of your string... put a NULL character at .

That is as simple as that...

M32Lib comes with a similar function to retrieve the executable paths after a call to GetModuleFileName... maybe you will find it useful...

PS: IIRC, shlwapi has some functions to deal with file strings... but your programs will need the shlwapi.dll that comes with IE4 or 5, I don't remember exactly...
The function is not not complex enough to add a required runtime to your program, imho...

I have coded a function for that in C there is some weeks... if you are interested I can post it here...
Posted on 2002-10-21 11:31:20 by JCP
I use this piece of code... (hehehe.. I know it's far from being fast but who cares ?)

 

;edi and esi free version

invoke GetModuleFileName, 0, ADDR Buffer, 256
mov eax, offset Buffer
add eax, 256
A1:
dec eax
cmp b$ [eax], "\"
jnz A1
mov b$ [eax+1], 0



I think it's faster than calling a strlen on a Buffer and then starting to scan backwards.

and

I think it's cleaner than to start byte scanning forwards saving your pointer to a "\" - restoring it again if there is another "\" and so forth...
Posted on 2002-10-21 12:03:20 by JimmyClif
Jimmyclif you are making the fundamental assumption that the un-used section of the buffer does not contain a slash character.

This may not be the case if the buffer has been poluted by repeated use.

The cleanest way is to keep a record of the position of the last found occurance.



mov eax, (offset buffer - 1)
xor ecx, ecx

@@:
inc eax
cmp BYTE PTR [eax], 0
je @F

cmp BYTE PTR [eax], '\\'
; Possibly replace with a cmov if .686 targeted code
jne @B
mov ecx, eax
jmp @B

@@:
or ecx, ecx
jz no_slash_found

mov BYTE PTR [ecx], 0


***** -> edit
However, having just spent the time to actually look at the API GetModuleFileName, there is a "safe" way to use Jimmyclif's algorithm with a slight modification.

Because GetModuleFileName's return value is the number of characters copied we can do this:


invoke GetModuleFileName, 0, ADDR Buffer, 256
or eax, eax ; check that something went into the buffer!
jz error_no_chars_copied

add eax, offset Buffer

@@:
dec eax
cmp BYTE PTR [eax], '\\'
jne @B

mov BYTE PTR [eax], 0


Mirno
Posted on 2002-10-21 12:17:57 by Mirno
Jimmy,

You use a trick because Win32 filenames are MAX_PATH long, which is equal to 256 or 255, IIRC...
Imho it is unsafe, and not that flexible...

- What happens if someday you deal with strings longer than 256 bytes ? Or worse, what happens if your buffer is smaller and there is no "\" character in this buffer... you will probably change a byte outside the range of your buffer... you can't predict the effects and it is also a common security flaw...
- What happens if your buffer has unitialized memory like it is often the case ?
There is a great risk that one of the unitialized bytes of your buffer is a "\" character... in this case your function will do nothing noticeable because it will never reach the "real string"...



I think it's cleaner than to start byte scanning forwards saving your pointer to a "\" - restoring it again if there is another "\" and so forth...


In fact, I think it is even cleaner than using strlen...
Posted on 2002-10-21 12:22:54 by JCP
For uninitialized Buffers:

Well, yes I do make the assumption that the Buffer is empty considering that I never used GetModuleFileName more than once in my app and I usually call it before I even hit WinMain. Most of the time I never even change that specific Buffer (besides putting a 0 in it) as it keeps a clean version of my AppPath.

/ Maybe I should have stated that it expects a clean buffer. :/

Mirno,

Good to know that it returns the number of chars... (tsk, sometimes I just don't bother reading Win32.hlp :tongue: )


Readio,

>>What happens if someday you deal with strings longer than 256 bytes ?

I dunno, maybe that would make a lot of apps not working anymore. Wdasm 8.3 (shareware) refuses to work already above 128 chars (iirc). IMO 256 (MAX_PATH) bytes is a fair amount of space and in case that isn't not big enough, well, the string will get truncated and AppPath would point into (possibly) a wrong directory. But still no biggie.

>>there is no "\" character in this buffer

This won't happen ;-) MS isn't going to change the whole 'working' filestructure and implementation inside their OS when they can put more graphic eye muchin' toys in it's GUI. ( ;) )
Posted on 2002-10-21 13:47:27 by JimmyClif

>>What happens if someday you deal with strings longer than 256 bytes ?

I dunno, maybe that would make a lot of apps not working anymore. Wdasm 8.3 (shareware) refuses to work already above 128 chars (iirc). IMO 256 (MAX_PATH) bytes is a fair amount of space and in case that isn't not big enough, well, the string will get truncated and AppPath would point into (possibly) a wrong directory. But still no biggie.


As I said, it is a trick, and each trick has a more or less hidden bad counterpart...
You are limiting your code to work for another platform (this function is no win32 dependant) and restrict code resuability...
You said it yourself: some apps are broken because of functions using constants like wdasm...
Imho the correct way to make your code work is to add a parameter to specify the string size...

Code reusability is something I learnt with C, not assembly but obviously, it is maybe even more important in assembly than C.


>>there is no "\" character in this buffer

This won't happen ;-) MS isn't going to change the whole 'working' filestructure and implementation inside their OS when they can put more graphic eye muchin' toys in it's GUI. ( )


Again, it seems that you don't think about future reusability of your code: what if it has to be an user input ? Users do mistakes, and even the most stupid they can find, it is what any programmer should have in mind if he wants to make a robust application...

My point is that you will probably one day have to reuse this code snippet with a string not feeded by GetModuleFileName...

Your code will work in some circumstances, but will probably not serve you for others purposes: intrinsically, for me, it is flawed, and saying it will work because Windows will never change this is putting the dust behind the carpet... nobody sees it, unless the carpet gets removed or moved for a reason or another...

I suggest you to be a bit more cautious with this kind of things: I have seen buffer overflow exploits for far less than that and nowadays writting secure code is not an option (and probably never been).

I know sometimes it is faster to optimize for one specific case, but I would never sacrify security to performance...
Posted on 2002-10-21 14:11:06 by JCP
Readio :)

Code Reusability is C not assembly. I don't mind reusing a nice snippet which does some work for me... but generally if you do use User Input you better make sure that the code does what it says... Which in some ways will be quicker just to write it anew than looking over an old piece of code.

But I have to admit that you're taking it all one step further (which I didn't even think about)
You think about a general proc where all you have to do is pass a pointer to a buffer and it returns either True or False with or without the AppPath in the Buffer. If we talk about reusability, this is good! If I'd intend to reuse a code over and over again, I make sure that every little detail fits and that a Buffer overflow etc won't happen. But generally a whole User-Safe-Reusable-Proc is <imo> overkill if all I want is strip a couple bytes of a buffer (and the coder should know - when which buffer is empty, clean or full). If this little snippet is to be in a proc with User-Friendly-Safe code than we can easily blow up that snippet to 5 times it size. If we call strlen inside it we can make it even bigger. My way (with Mirno's change on adding the lenght of the string after the call to the offset of the buffer), is (in this example) working! clean! right under your eyes! w/o any baggage! It might not be valid for a Windows Version in 5-10 years but certainly the whole world turned around a couple times and in 5 years the app will be renundant anyways, so that little cosmetic error (trick) will never be found.



:grin:
Posted on 2002-10-21 15:31:38 by JimmyClif

Code Reusability is C not assembly.


Code reusability is a programming concept and not langage dependant... I think it is important in any langages...
Many good programmers I know have their own personal library...
It is maybe a concept popular in HLL, but it is not because we are coding in assembly that all the good concepts of HLL should be forgotten, or volontary ignored imho...

Code reusability is something true, and real : the MASM32 library is the living proof of this...
This library is flexible and reusable enough for most programmers uses, to not say all...
Would you mind to rewrite a new dwtoa each time you use it ? Definitely no...


But I have to admit that you're taking it all one step further (which I didn't even think about)
You think about a general proc where all you have to do is pass a pointer to a buffer and it returns either True or False with or without the AppPath in the Buffer. If we talk about reusability, this is good! If I'd intend to reuse a code over and over again, I make sure that every little detail fits and that a Buffer overflow etc won't happen. But generally a whole User-Safe-Reusable-Proc is <imo> overkill if all I want is strip a couple bytes of a buffer (and the coder should know - when which buffer is empty, clean or full). If this little snippet is to be in a proc with User-Friendly-Safe code than we can easily blow up that snippet to 5 times it size. If we call strlen inside it we can make it even bigger. My way (with Mirno's change on adding the lenght of the string after the call to the offset of the buffer), is (in this example) working! clean! right under your eyes! w/o any baggage!


Secure doesn't mean bloated...
I have written a backward memory filling routine processing 4 bytes at a time and that should take care to prevent some special overflow cases (because it is optimized): all works well, fast, is secure and is not bloated...
The equilibre between security, code tightness and speed is possible...
Mirno's solution is somewhat what I talked about, and it doesn't end up very bloated or slow...
For such a simple algorithm, there is not many security tests to perform...

What you are saying is like wanting to drive the fastest possible on the road, ignoring the basic security... who cares if you go fast if you never reach your destination because of an accident ? In other words, who cares if your program uses two cycles less if it bugs pathetically by GPFing ? Do not rely on undefined behaviours... but don't be paranoid either...

Well, just imagine a procedure/function that receive two arguments: a pointer to the beginning of the string and the size of the string... all will work well...

Your code is working in some cases and today because the maximum path size is 256: a better concepted code would work in any case and forever and a well programmed code won't be much smaller and bigger...


It might not be valid for a Windows Version in 5-10 years but certainly the whole world turned around a couple times and in 5 years the app will be renundant anyways, so that little cosmetic error (trick) will never be found.


What you call a little cosmetic error is one of the most popular exploit used by hackers to intrude computers and systems...
It is not me that says it but computer security reports...
Posted on 2002-10-21 16:04:29 by JCP
thx for your reply....
when I post the newthead it is time to bed in my TimeZoom (GMT+8),
So I am go to sleep 10 minits later.
It's interest things that one timezoom's people sleeping when another timezoom's
programmer's visiting this messga-thead.
:)
yes,In my past some little exe I used


invoke GetModuleFileName,NULL,addr szFull,MAX_PATH

and search backward for "\" and replace it with a char(0).
In my first GUI programe,I use


invoke GetCurrentDirectory,MAX_PATH,addr szDir

in winMain first wo get the currentpath,but some day's later I found If startup it from a shortcut-link,
it will get the path where that shortcut placed.
for example from desktop It back to me"f:\documents and settings\administrator\desktop",
so I try to use GetModuleFileName API in my second little exe(a umeviewer).

I am writing code for an 2-color PDA with 6502 some years,
So when I found there an MASM can write program for win some month ago,I can't believe that.
I love that MASM can product cute exe,so I can add more and more code in my exe and the exe can be counting in kbyte,
If I add the same skin in MFC,the exe file will grow fast more than 1 Mbyte.
Some days ago I am intersting for made software like apple's MacOS 8's style so I try to do it with VC,Delphi,BC,
at least I fround the ASM is fast and smallest,
and....
the GDI code is such tried to GetDC,to paint a line, to made the mouse hot-track effects.
At lease I complete the MacOS8 style clone under win,like the picture I attached.
Most control where ownerdraw,I am hate windows "3D" Controls so I flat then,;)
;============================================================================

Yes ,Code reusability is most OOB language's feather,In delphi,If you want to set an control's color,
Just code
Control.color:=$00FFFFFF
,one Module in the exefile will earse the background and set it to white.
or If you click an button,another Module will jump to somewhere if you choose button.onclick=some codes.
these Module is between API and exe,sure it is code reusable.
I think in Win32 SDK program,
API between system and our code,
It is another type of code reusablity,:confused:
Posted on 2002-10-21 19:42:23 by Const.Ex
?Oh,
I am edited some value defined in windows.inc
after I installed MASM
#define MAX_PATH equ 512
and some other value for larger and larger HardDrive,
Deeper and deeper path.
Posted on 2002-10-21 20:29:10 by Const.Ex
As well as you're right... you can't deny the wrongs either....


Well, just imagine a procedure/function that receive two arguments: a pointer to the beginning of the string and the size of the string... all will work well...


What if now you need to search for a "/" instead of a "\" ? Open up the library you know so well and change it? Rip out that piece of the library rename it and paste it into your code so you won't create any naming conflicts? Last choice results in 2 copies of the same proc which change only by one byte, first choice breaks your App if you have already a couple calls to it (and probably some older apps if you forget to change it back)

So, for the perfect routine a correct calling function would be then 3 arguments: 1 for the Buffer, 1 for the size and the last one for the char to search. And this does lead to bloat. Here we'd get already 3 pushes, the usual save and restore stack pointer game, and some error checking in case the Dummy-User gave you wrong input... etc.. etc... and finally our routine.

And we knew in advance that the buffer would never be above 256 bytes (unless M$ comes along and changes the rules) and that the Buffer was considered to be empty. (which I should have mentionned).

I don't deny code reusability but the reason we program in assembler is not to wrap up single 4 lines of code into a 20 line proc just so that it is absolutely idiot proof :) as we should know when and where security should be appropriate.

For the masmlib - we all know that it's quite useful... and that's why we use it. :alright: but even the masmlib has procs where Hutch-- says that we have to pass this and that param. If we don't it will crash.
Security checking is mostly not needed as we should know what we're doing!
Posted on 2002-10-21 20:38:54 by JimmyClif
Const-Ex,

Missed your question as I left the comp for quite awhile just leaving it as is ;)

>>It is another type of code reusablity<<

Yep... right there... that's reusability to the furtest extend where there's no more 'I want to do his by hand' left. I think this is how big languages evolved. Wrapper around wrapper around wrapper around wrapper.

Don't forget to define your Buffers too as MaxPath size and that should do it :)
Posted on 2002-10-21 21:08:25 by JimmyClif
I read some Tutorials code and noticed the


.data?
szDirBuf DD MAX_PATH(or Others Defined Value) dup (?)
or
.data
szDirBuf DB MAX_PATH dup (0)

are useful
thank for you remind of me.
Er...
just in me current exe I forgot it.
Posted on 2002-10-21 21:38:02 by Const.Ex

Yes ,Code reusability is most OOB language's feather,In delphi,If you want to set an control's color,
Just code
Control.color:=

Yes ,Code reusability is most OOB language's feather,In delphi,If you want to set an control's color,
Just code
Control.color:=$00FFFFFF
,one Module in the exefile will earse the background and set it to white.
or If you click an button,another Module will jump to somewhere if you choose button.onclick=some codes.
these Module is between API and exe,sure it is code reusable.
I think in Win32 SDK program,
API between system and our code,
It is another type of code reusablity


No,
Reusable code is not always OOP...
Reusable code is part of the code design, not the programming itself...


And we knew in advance that the buffer would never be above 256 bytes (unless M$ comes along and changes the rules) and that the Buffer was considered to be empty. (which I should have mentionned).


It won't be less, but it can be above in the future... (and some headers file even define MAX_PATH differently)...
Remember "Nobody will ever need more than 640kb"...


So, for the perfect routine a correct calling function would be then 3 arguments: 1 for the Buffer, 1 for the size and the last one for the char to search. And this does lead to bloat.


That is a typical memsearch function then...


3 pushes, the usual save and restore stack pointer game


Oh my! :eek:
And you can skip the prolog and epilog code... or write macros if you don't want calling overhead...


and some error checking in case the Dummy-User gave you wrong input... etc.. etc... and finally our routine.


A slash search routine is not exactly speed critical: I don't say it is an excuse to make it slow...
I think you get me wrong: I'm not talking about redundant checking but about security control...
Your code will work in some cases and makes too much assumptions to be reliable...


and that the Buffer was considered to be empty. (which I should have mentionned).


Here your argument about code bloatness catches you back: what do you do if your buffer is not empty ? (unitialized memory is frequent). If you already used this buffer for this function or another and have to recall it: you will have to call RtlZeroMemory or something like that to prevent your function crashing...
Are you sure your solution is not the most bloated in this case ? (and it is not a rare one).


For the masmlib - we all know that it's quite useful... and that's why we use it. but even the masmlib has procs where Hutch-- says that we have to pass this and that param. If we don't it will crash.


Of course, to use any function, there is rules...
Passing a bad size operand or something like that is a mistake depending of the caller program... but if you check the code carefully, there is bound checking and error checking to have a secure code...


Yep... right there... that's reusability to the furtest extend where there's no more 'I want to do his by hand' left. I think this is how big languages evolved. Wrapper around wrapper around wrapper around wrapper.
FFFFFF
,one Module in the exefile will earse the background and set it to white.
or If you click an button,another Module will jump to somewhere if you choose button.onclick=some codes.
these Module is between API and exe,sure it is code reusable.
I think in Win32 SDK program,
API between system and our code,
It is another type of code reusablity


No,
Reusable code is not always OOP...
Reusable code is part of the code design, not the programming itself...


And we knew in advance that the buffer would never be above 256 bytes (unless M$ comes along and changes the rules) and that the Buffer was considered to be empty. (which I should have mentionned).


It won't be less, but it can be above in the future... (and some headers file even define MAX_PATH differently)...
Remember "Nobody will ever need more than 640kb"...


So, for the perfect routine a correct calling function would be then 3 arguments: 1 for the Buffer, 1 for the size and the last one for the char to search. And this does lead to bloat.


That is a typical memsearch function then...


3 pushes, the usual save and restore stack pointer game


Oh my! :eek:
And you can skip the prolog and epilog code... or write macros if you don't want calling overhead...


and some error checking in case the Dummy-User gave you wrong input... etc.. etc... and finally our routine.


A slash search routine is not exactly speed critical: I don't say it is an excuse to make it slow...
I think you get me wrong: I'm not talking about redundant checking but about security control...
Your code will work in some cases and makes too much assumptions to be reliable...


and that the Buffer was considered to be empty. (which I should have mentionned).


Here your argument about code bloatness catches you back: what do you do if your buffer is not empty ? (unitialized memory is frequent). If you already used this buffer for this function or another and have to recall it: you will have to call RtlZeroMemory or something like that to prevent your function crashing...
Are you sure your solution is not the most bloated in this case ? (and it is not a rare one).


For the masmlib - we all know that it's quite useful... and that's why we use it. but even the masmlib has procs where Hutch-- says that we have to pass this and that param. If we don't it will crash.


Of course, to use any function, there is rules...
Passing a bad size operand or something like that is a mistake depending of the caller program... but if you check the code carefully, there is bound checking and error checking to have a secure code...


Yep... right there... that's reusability to the furtest extend where there's no more 'I want to do his by hand' left. I think this is how big languages evolved. Wrapper around wrapper around wrapper around wrapper.


No. That depends of many factors in fact, and it is not only reusability... because it is a complex engine and each code part have to interact with the other...
Code reusability doesn't always imply wrappers and things like that...

In fact, a non-flexible code will result in more overhead from the calling function that has to take care of what your function doesn't (ie, cleaning the buffer).
Your function is small, but you only move the overhead somewhere else... (the caller) which is imho maybe worse because the caller must do the job each time you use the function...

A basic slash search routine only require two arguments to be secure: it is worth it, imho and is not that bloated... and if you need a GetAppPath, it can be a function with only one argument (a pointer to the destination string) like it is in the m32lib IIRC.
I understand your argument about bloatness but all is about not being excessive in a way or another, and thinking about when and why you will have to reuse this code someday... a professionnal programmer simply can't afford to recode each function each time.
Posted on 2002-10-22 01:37:06 by JCP