Small app, a log scrubber, runs fine on it's first pass, but loads the process to 100% if run again because it fails to delete LogFile.txt.
In the Get_ELog_List proc if I put breakpoints after GetFileSize, ReadFile, CloseHandle, DeleteFile and run the program to the breakpoints everything works. If I put a single breakpoint after DeleteFile the first 3 calls give me Invalid_Handle_Value error and the DeleteFile returns a File_Not_Found error. It almost looks as if the code is too fast for the OS and I need to wait after every call to let the OS catch up.
Seems to "work" , but you may consider using Window's Event Log Functions (as Vortex suggest).
Also, your call to Check_Admin is missplaced -> move it to WM_CREATE or the startup code before WinMain.
I'll move the admin check. I must have missed vortex's post will give it a try.
The program works on the first pass but fails to delete the txt file it creates so it fails if you try to run it a second time. However it may be my version of windows.
Thanks.
OK, I found one problem: you do not wait for the created processes -> WaitForSingleObject(...,pi.hProcess,...). Also, you must close the Process handle.
You may also move the deletion-process into a seperate thread...
The placement of the admin call in the main loop explains the high CPU usage. For every tiny movement of the mouse, that proc gets called a hundred times.
Re WaitForSingleObject, here is an excerpt from MasmBasic's Launch (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1044) macro - may save you some typing ;-)
xor ecx, ecx ; using ecx as NULL saves some bytes
invoke CreateProcess, ecx, ; no pathname
cmdline, ; the only bit that REALLY counts...!
ecx, ecx, sat.bInheritHandle, ; lpProcessAttributes, lpThreadAttributes, bInheritHandles
edx, ecx, ecx, ; dwCreationFlags, lpEnvironment, lpCurrentDirectory
ebx, ; read from STARTUPINFO (ebx=addr sinfo)
addr pinfo ; write to PROCESS_INFORMATION
xor ebx, ebx ; flag fail
.if eax
mov ebx, pinfo.hProcess ; wow, we got a handle! Actually, we got two...
.if ebx
invoke WaitForSingleObject, ebx, edi ; specify milliseconds here
push ecx ; create a stack slot for the exit code
invoke GetExitCodeProcess, ebx, esp ; esp=addr ExCode
invoke CloseHandle, ebx
invoke CloseHandle, pinfo.hThread
pop edx ; retrieve exit code from the stack, return in edx
.endif
.endif
Changed the location of the Admin Check, added a wait WaitForSingleObject and CloseHandle. Works better can't find any errors and the process appears to wait. Not sure if the call WaitForSingleObject is structured properly it seemed too easy. Included a picture of my Admin logs after a morning test new boards.
The check for admin don't work:
Quote
Msdn sample
BOOL IsUserAdmin(VOID)
/*++
Routine Description: This routine returns TRUE if the caller's process
is a member of the Administrators local group. Caller is NOT expected
to be impersonating anyone and is expected to be able to open its own
process and process token.
Arguments: None.
Return Value:
TRUE - Caller has Administrators local group.
FALSE - Caller does not have Administrators local group. --
*/
{
BOOL b;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID AdministratorsGroup;
b = AllocateAndInitializeSid(
&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&AdministratorsGroup);
if(b)
{
if (!CheckTokenMembership( NULL, AdministratorsGroup, &b))
{
b = FALSE;
}
FreeSid(AdministratorsGroup);
}
return(b);
}
IsUserAnAdmin function :
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\shell32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\shell32.lib
.data
text1 db 'The user is not a member of the Administrators group',0
text2 db 'The user is a member of the Administrators group',0
capt db 'IsUserAnAdmin',0
array dd text1,text2
.code
start:
invoke IsUserAnAdmin
lea edx,[array+4*eax]
invoke MessageBox,0,DWORD PTR [edx],ADDR capt,MB_OK
invoke ExitProcess,0
END start
Works perfectly, Erol :t
I wonder if it's still available on Win7 & Win8, though ::)
The Admin check appears to work fine on windows 7, but I'll try thhe ToutEnMasm's code and see what happens.
I want to thank everbody for all their help. Sometimes I get so wrapped up in solving the problems in the code I forget to.
Thank You.
Checked on the Admin. In windows, at least on my own PC, I log in as Administrator but I still have to run the program as an Administrator from the right button menu. The check in the program as it exists checks to make sure that I am running it this elevated state. I believe that ToutEnMasm and Vortex's code check the initial log on conditions to make sure the user is logged in as an administrator. Both administrator procs are probably necessary for the program to function properly. The first to check that the user is indeed an Administrator and the second to check that the program is being run in an elevated (administrator) state.
Here the translated code from MSDN,work well on my XP3
.data
;SECURITY_NT_AUTHORITY TEXTEQU <0,0,0,0,0,5>
NtAuthority SID_IDENTIFIER_AUTHORITY <>
AdministratorsGroup dd 0
.code
Check_Admin proc
LOCAL Is_Admin:DWORD
mov eax,offset NtAuthority.Value
mov byte ptr [eax+5],5 ;SECURITY_NT_AUTHORITY TEXTEQU <0,0,0,0,0,5>
invoke AllocateAndInitializeSid,addr NtAuthority,2,SECURITY_BUILTIN_DOMAIN_RID,\
DOMAIN_ALIAS_RID_ADMINS,0, 0, 0, 0, 0, 0,addr AdministratorsGroup
.if eax != 0
mov Is_Admin,eax
invoke CheckTokenMembership,NULL,AdministratorsGroup,addr Is_Admin
.if eax == 0
mov Is_Admin,0
.endif
.endif
mov eax,Is_Admin
ret
Check_Admin endp
Hi Jochen,
Here is what I found :
QuoteRemarks
This function is a wrapper for CheckTokenMembership. It is recommended to call that function directly to determine Administrator group status rather than calling IsUserAnAdmin.
Requirements
Minimum supported client
Windows XP
Minimum supported server
Windows Server 2003
End of client support
Windows Vista
End of server support
Windows Server 2008
http://msdn.microsoft.com/en-us/library/windows/desktop/bb776463(v=vs.85).aspx
I tried ToutEnMasm's code snippet, it runs fine. There is one declaration in the data statement that I don't understand.
NtAuthority SID_IDENTIFIER_AUTHORITY <>
Thanks. :greenclp:
Quote
.const
SID_IDENTIFIER_AUTHORITY STRUCT DEFALIGNMASM
Value BYTE 6 dup (?)
SID_IDENTIFIER_AUTHORITY ENDS
.data
NtAuthority SID_IDENTIFIER_AUTHORITY <> ;name of the struct in data
c++ initialyse the value of each byte with that <0,0,0,0,0,5>
Masm don't accept, so init is made on data with a pointer on NtAuthority.Value + n BYTE