NULL pointer given, Win32API

Ok, now the EventLog#close method is dying. It’s returning “the handle
is invalid”.

What am I doing wrong?

require "Win32API"
module Win32

CloseEventLog = Win32API.new(“advapi32”,“CloseEventLog”,“P”,“I”)
FormatMessage =
Win32API.new(“kernel32”,“FormatMessage”,“LPLLPLP”,“L”)
GetLastError = Win32API.new(“kernel32”,“GetLastError”,[],“L”)
OpenEventLog = Win32API.new(“advapi32”,“OpenEventLog”,“PP”,“P”)

ERROR_SUCCESS = 0x00

Error formatting constants

FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100
FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200
FORMAT_MESSAGE_FROM_STRING = 0x00000400
FORMAT_MESSAGE_FROM_HMODULE = 0x00000800
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000
FORMAT_MESSAGE_MAX_WIDTH_MASK = 0x000000FF

class Win32EventLogError < StandardError; end

class EventLog
def initialize(source,machine=0)
lpSource = [source].pack(“p”)

     unless 0 == machine
        lpMachine = [machine].pack("p")
     end
     
     begin
        @hEventLog = OpenEventLog.call(machine,source)
     rescue
        raise Win32EventLogError, get_error
     end
  end
  
  def close
     if 0 == CloseEventLog.call(@hEventLog)
        raise Win32EventLogError, get_error
     end
  end
  
  def get_error(error_code=GetLastError.call)
     msg = " " * 255
     FormatMessage.call(
        FORMAT_MESSAGE_FROM_SYSTEM +
        FORMAT_MESSAGE_ARGUMENT_ARRAY,
        '',
        error_code,
        0, 
        msg,
        255,
	''
     )
     msg.gsub!(/\000/, '')
     msg.strip!
     msg
  end

end # EventLog
end # Win32

if $0 == FILE
include Win32
e = EventLog.new(“Application”)
e.close # Error
end

Hi, Dan

Ok, now the EventLog#close method is dying. It’s returning “the handle
is invalid”.

What am I doing wrong?

Treat handle as integer.

require “Win32API”
module Win32

CloseEventLog = Win32API.new(“advapi32”,“CloseEventLog”,“P”,“I”)

should be CloseEventLog = Win32API.new(“advapi32”,“CloseEventLog”,“I”,“I”)

FormatMessage =
Win32API.new(“kernel32”,“FormatMessage”,“LPLLPLP”,“L”)
GetLastError = Win32API.new(“kernel32”,“GetLastError”,,“L”)
OpenEventLog = Win32API.new(“advapi32”,“OpenEventLog”,“PP”,“P”)

should be OpenEventLog = Win32API.new(“advapi32”,“OpenEventLog”,“PP”,“I”)

Regards,

Park Heesob

Hi,

[snipped beyond recognition]

require “Win32API”
FormatMessage = Win32API.new(“kernel32”,“FormatMessage”,“LPLLPLP”,“L”)
GetLastError = Win32API.new(“kernel32”,“GetLastError”,,“L”)

  def get_error(error_code=GetLastError.call)
     msg = " " * 255
     FormatMessage.call(
        FORMAT_MESSAGE_FROM_SYSTEM +
        FORMAT_MESSAGE_ARGUMENT_ARRAY,
        '',
        error_code,
        0,
        msg,
        255,
        ''
     )
     msg.gsub!(/\000/, '')
     msg.strip!
     msg
  end

GetLastError() using Win32API isn’t very effective IMHE.

By the time you get around to calling it, it’s been zapped by other
API calls that have been made on your behalf.
While you’re testing, though, you really need to see these errors.

If you’ve self-built ruby, you might try this version:
http://www.d10.karoo.net/ruby/Win32API.c (temporary)

(Hope you can scrape it off your browser :slight_smile:

Added class methods:

Win32API.lasterr
Win32API.message(code=lasterr) (produces ‘FormatMessage’ from system)

(e.g.)
puts Win32API.message unless Win32API.lasterr == 0

If it hasn’t become useful within 15 minutes, pretend you didn’t see this post :slight_smile:

Good luck,

daz

···

“Berger, Daniel” djberge@qwest.com wrote:

“daz” dooby@d10.karoo.co.uk wrote in message news:spSdnTTB4Yt61JXdSa8jmw@karoo.co.uk

Hi,

[snipped beyond recognition]

require “Win32API”
FormatMessage = Win32API.new(“kernel32”,“FormatMessage”,“LPLLPLP”,“L”)
GetLastError = Win32API.new(“kernel32”,“GetLastError”,,“L”)

  def get_error(error_code=GetLastError.call)
     msg = " " * 255
     FormatMessage.call(
        FORMAT_MESSAGE_FROM_SYSTEM +
        FORMAT_MESSAGE_ARGUMENT_ARRAY,
        '',
        error_code,
        0,
        msg,
        255,
        ''
     )
     msg.gsub!(/\000/, '')
     msg.strip!
     msg
  end

GetLastError() using Win32API isn’t very effective IMHE.

By the time you get around to calling it, it’s been zapped by other
API calls that have been made on your behalf.
While you’re testing, though, you really need to see these errors.

If you’ve self-built ruby, you might try this version:
http://www.d10.karoo.net/ruby/Win32API.c (temporary)

(Hope you can scrape it off your browser :slight_smile:

Added class methods:

Win32API.lasterr
Win32API.message(code=lasterr) (produces ‘FormatMessage’ from system)

(e.g.)
puts Win32API.message unless Win32API.lasterr == 0

If it hasn’t become useful within 15 minutes, pretend you didn’t see this post :slight_smile:

Good luck,

daz

Very nice! With this I can more easily define my own Exception classes, e.g.:

class Win32FooError < StandardError
def initialize(msg=Win32API.message)
super
end
end

Please commit!

Regards,

Dan

···

“Berger, Daniel” djberge@qwest.com wrote:

“daz” dooby@d10.karoo.co.uk wrote in message news:spSdnTTB4Yt61JXdSa8jmw@karoo.co.uk

Hi,

[snipped beyond recognition]

require “Win32API”
FormatMessage = Win32API.new(“kernel32”,“FormatMessage”,“LPLLPLP”,“L”)
GetLastError = Win32API.new(“kernel32”,“GetLastError”,,“L”)

  def get_error(error_code=GetLastError.call)
     msg = " " * 255
     FormatMessage.call(
        FORMAT_MESSAGE_FROM_SYSTEM +
        FORMAT_MESSAGE_ARGUMENT_ARRAY,
        '',
        error_code,
        0,
        msg,
        255,
        ''
     )
     msg.gsub!(/\000/, '')
     msg.strip!
     msg
  end

GetLastError() using Win32API isn’t very effective IMHE.

By the time you get around to calling it, it’s been zapped by other
API calls that have been made on your behalf.
While you’re testing, though, you really need to see these errors.

If you’ve self-built ruby, you might try this version:
http://www.d10.karoo.net/ruby/Win32API.c (temporary)

(Hope you can scrape it off your browser :slight_smile:

Added class methods:

Win32API.lasterr
Win32API.message(code=lasterr) (produces ‘FormatMessage’ from system)

(e.g.)
puts Win32API.message unless Win32API.lasterr == 0

If it hasn’t become useful within 15 minutes, pretend you didn’t see this post :slight_smile:

Good luck,

Oops, I think I spoke too soon. I’m getting false positives.
Consider:

require “Win32API”
class Foo
GetFileAttributes =
Win32API.new(“kernel32”,“GetFileAttributes”,“P”,“I”)
READONLY = 0x00000001

def read_only?(file)
rv = GetFileAttributes.call(file) & READONLY
puts Win32API.message unless Win32API.lasterr == 0
return true if rv > 0
false
end
end

It appears that, even though GetFileAttributes.call works fine (it
returns true or false in experiments), Win32API.lasterr is returning
127, “The specified procedure could not be found”. What’s up?

Regards,

Dan

···

“Berger, Daniel” djberge@qwest.com wrote:

For GetFileAttributes(), I’d do something like …

require “Win32API”
class Foo
GetFileAttributes = Win32API.new(“kernel32”,“GetFileAttributes”,“P”,“I”)
READONLY = 0x00000001

def read_only?(file)
rv = GetFileAttributes.call(file)
(rv == -1) and raise(RuntimeError, “Win32API.message here”)
(rv & READONLY)==1
end
end

<Win32 Programmer’s Reference - GetLastError() - Remarks> says:

Most functions in the Win32 API that set the thread’s

last error code value set it when they fail; a few functions

set it when they succeed.

On your system, it looks like SetLastError(0) is not (by design)
being used after success.
(Failure here is indicated by a function return value of 0xFFFFFFFF;
the internal ‘last error’ is left unchanged. That must have been
127 before (or during) the run your example above.)

If Win32API doesn't find "GetFileAttributes" ... it appends 'A' and tries "GetFileAttributesA" and the 'real last error code' would then be 127 ("proc not found") unless the second call sets 'last error' to zero on success.

Calling GetLastError() is not the way to check for success/failure
in Win32 API calls (as you know). Apologies if my trivial example
suggested that calling Win32API.lasterr would be any different.

Cheers,

daz

···

“Daniel Berger” djberg96@hotmail.com wrote:

Oops, I think I spoke too soon. I’m getting false positives.
Consider:

require “Win32API”
class Foo
GetFileAttributes = Win32API.new(“kernel32”,“GetFileAttributes”,“P”,“I”)
READONLY = 0x00000001

def read_only?(file)
rv = GetFileAttributes.call(file) & READONLY
puts Win32API.message unless Win32API.lasterr == 0
return true if rv > 0
false
end
end

It appears that, even though GetFileAttributes.call works fine (it
returns true or false in experiments), Win32API.lasterr is returning
127, “The specified procedure could not be found”. What’s up?