# Finding Shared Directories in Assembly

## Main Question or Discussion Point

Finding "Shared" Directories in Assembly

For my next project, I am making a program which searches for all of the shared directories on a computer. My idea is if the directory contains the string "share", then it must be shared.

For this, I wrote a function to convert the directory name to upper-case letters. After this, the program checks character-by-character for "SHARE". I have no errors in this code when compiled by itself. Once I introduce my directory-search function, I errors. Please look at my code and let me know what I have done wrong.
Code:
.386
.MODEL FLAT

EXTRN	FindFirstFileA		:PROC
EXTRN	MessageBoxA		:PROC
EXTRN	FindNextFileA		:PROC
EXTRN	FindClose		:PROC
EXTRN	SetCurrentDirectoryA	:PROC
EXTRN	lstrcpyA		:PROC

MAX_PATH			equ	256
FILE_ATTRIBUTE_DIRECTORY	equ	00000010h

WIN32_FIND_DATA STRUC
dwFileAttributes	dd ?
ftCreationTime		dq ?
ftLastAccessTime	dq ?
ftLastWriteTime		dq ?
nFileSizeHigh		dd ?
nFileSizeLow		dd ?
Reserved0		dd ?
Reserved1		dd ?
cFileName		db MAX_PATH dup(?)
cAlternateFileName	db 14 dup(?)
WIN32_FIND_DATA ENDS

.DATA
hFind		dd ?
szMask		db "*.*", 0
szBackDir	db "..", 0
szDirectory	db MAX_PATH dup(?)
win32FindData	WIN32_FIND_DATA <?>
szDrive		db "C:\", 0

.CODE
MAIN:
push	offset szDrive
call	SetCurrentDirectoryA

findFirstFile:
push	offset win32FindData
push	offset szMask
call	FindFirstFileA				; find first file in C:\ drive
mov	[hFind], eax

checkType:
cmp	eax, 0					; no files?
je	downDirectory
cmp	byte ptr [win32FindData.cFileName], "."
je	findNextFile
cmp	[win32FindData.dwFileAttributes], 10h
je	upDirectory
cmp	[win32FindData.dwFileAttributes], 30h
je	upDirectory

findNextFile:
push	offset win32FindData
push	[hFind]
call	FindNextFileA
jmp	checkType

upDirectory:
push	offset win32FindData.cFileName
push	offset szDirectory
call	lstrcpyA

mov	eax, offset szDirectory

cmp	byte ptr [eax], 90				; already uppercase? (90 = Z)
jle	toUpperCase
xor	byte ptr [eax], 32				; convert

toUpperCase:
inc	eax
cmp	byte ptr [eax], 0				; at end of string?
je	endOfString
cmp	byte ptr [eax], 90				; already uppercase?
jle	toUpperCase
xor	byte ptr [eax], 32				; convert
jmp	toUpperCase

endOfString:
mov	eax, 0
mov	eax, offset szDirectory

searchShare:
inc	eax
cmp	byte ptr [eax], 0				; end of string?
jne	noShare
cmp	byte ptr [eax], "S"				; check for S
jne	searchShare
cmp	byte ptr [eax + 1], "H"				; check for H
jne	searchShare
cmp	byte ptr [eax + 2], "A"				;
jne	searchShare
cmp	byte ptr [eax + 3], "R"				;
jne	searchShare
cmp	byte ptr [eax + 4], "E"				;
jne	searchShare

push	0
push	offset szDirectory
push	offset szDirectory
push	0
call	MessageBoxA					; display directory

noShare:
push	offset szDirectory
call	SetCurrentDirectoryA
cmp	eax, 0
je	findNextFile

push	hFind
jmp	findFirstFile

downDirectory:
push	offset szBackDir
call	SetCurrentDirectoryA
push	[hFind]
call	FindClose
pop	[hFind]
cmp	[hFind], 0
jne	findNextFile

theEnd:
ret
END	MAIN
I am using TASM 5.0 and TLINK32 to compile.

Thanks in advance!

## Answers and Replies

Related Programming and Computer Science News on Phys.org
Yes, but that is not my problem.
Code:
[ ... ]
cmp	eax, -1					; INVALID_HANDLE_VALUE
[ ... ]
Just has the code loop infinitely.

The code sperately executes fine (the enumerate folders function works by itself; the convert-to-uppercase function works by itself; and the search for "SHARE" function works by itself). When put together, the program fails. It is not until it finds a directory which contains "SHARE" that I get an error.

Any ideas?

rcgldr
Homework Helper
What it the attribute of the "SHARE" entries in the directory? If "SHARE" shows up as a directory, your program could be trying to open up "SHARE" as a sub-directory.

Also, how are you handing the directory entries "." and "..", which should be ignored?

What it the attribute of the "SHARE" entries in the directory?
"SHARE" is in the directory's name (WIN32_FIND_DATA.cFileName).
If "SHARE" shows up as a directory, your program could be trying to open up "SHARE" as a sub-directory.
I'm not sure I understand what you mean by this. However, the program would display a message box before trying to change directories, which it is not doing.
Also, how are you handing the directory entries "." and "..", which should be ignored?
With the following code:
Code:
	[ ... ]
cmp	byte ptr [win32FindData.cFileName], "."
je	findNextFile
[ ... ]
The first line checks if the first byte in the string is a period ("."). If it is, the directory is skipped by jumping to the label findNextFile.

rcgldr
Homework Helper
I don't understand this sequence in your code:

Code:
	push	hFind
jmp	findFirstFile
Note that SetCurrentDirectory has no effect on FindNextFile, since FindNextFile uses the data in the WIN32_FIND_DATA STRUC to keep track of where it is at.

For each new directory you encounter, you need to use a new instance of WIN32_FIND_DATA STRUC (win32FindData), and a new instance of handle (hFind), to call FindFirstFile.

My method for scanning a directory tree is to use an array of WIN32_FIND_DATA STRUC, and an array of handles (from FindFirstFile). The number of elements is the max level of nesting of directories you program will handle. 64 should be enough.

The alternative is to place these variables on the stack and use recursive calls.

The idea in that code was to save the hFind handle, then jump to the findFirstFile label.

For each new directory you encounter, you need to use a new instance of WIN32_FIND_DATA STRUC (win32FindData), and a new instance of handle (hFind), to call FindFirstFile.
I disagree. The when the attached file is compiled, it works perfectly. It will display every directory on the C:\ drive without using multiple instances of WIN32_FIND_DATA and my hFind handle.

My method for scanning a directory tree is to use an array of WIN32_FIND_DATA STRUC, and an array of handles (from FindFirstFile). The number of elements is the max level of nesting of directories you program will handle. 64 should be enough.
Are you saying you create 64 different "win32FindData" structures? If so, this does not sound logical...

The alternative is to place these variables on the stack and use recursive calls.
Place the directory names on the stack? There will be hundreds of directory names per drive, so I do not think this would work either...

Thank you very much for your response though, it's nice to know someone is willing to help me.

#### Attachments

• 1.6 KB Views: 170
rcgldr
Homework Helper
The when the attached file is compiled, it works perfectly. It will display every directory on the C:\ drive without using multiple instances of WIN32_FIND_DATA and my hFind handle.
I meant nested directories. For example, you can find c:\windows with a FindFirstFile of "c:\*.*", but to find c:\windows\system32, you'll need to use a FindFirstFile with "c:\windows\*.*". Each level of nesting requires a new instance of the handle, and I thought a new instance of the find structure, and a call to FindFirstFile. I'm not sure where windows saves it's current search progress, in the find data structure or in some internal structure related to the handle. Using a new instance of the find data structure for each level of nesting works, but I don't know if it's required.

Last edited:
rcgldr
Homework Helper
I meant nested directories. For example, you can find c:\windows with a FindFirstFile of "c:\*.*", but to find c:\windows\system32, you'll need to use a FindFirstFile with "c:\windows\*.*". Each level of nesting requires a new instance of the handle, and I thought a new instance of the find structure, and a call to FindFirstFile. I'm not sure where windows saves it's current search progress, in the find data structure or in some internal structure related to the handle. Using a new instance of the find data structure for each level of nesting works, but I don't know if it's required.
Mutiple instances of the find data structure are not required. The find data structure is described as only being used for output. This means that you just need a new instance of a handle and a call to findfirstfile for each directory you switch into.

Last edited:
Then why does the enumerate directory code work?

rcgldr
Homework Helper
Looks like you should have a "push [hFind]" instead of a "push hFind" just before "downDirectory". I'm guessing this is the problem since you're pushing the offset to hFind instead of it's value, if I understand TASM syntax. It also seems that you should have a "push 0BAADF00Dh" before "FindFirstFile:".

Shoudln't there be a check for EAX == -1 after the call to FindFirstFile?

Last edited:
rcgldr
Homework Helper
No response for a while. Did the previous post help solve the problem (specifcally using "push [hfind]")?