UPDATE! The community will be go into read-only on April 19, 8am Pacific in preparation for migration on April 21. Read more.
UPDATE! The community will be go into read-only on April 19, 8am Pacific in preparation for migration on April 21.Read more.
Absent Member.
Absent Member.
1812 views

Dll Call --> ERROR_INVALID_HANDLE

Hi all,

I'm trying to call a function in the Novell client32 version 4.91.5.20080922. The dll is the "netwin32.dll". Running on WinXP.
I'm getting a ERROR_INVALID_HANDLE when I try and call NWDSList or NWDSRead.

here is the code I'm using:

It's in Autohotkey.. http://www.autohotkey.com/ , but the format is pretty simple:
http://www.autohotkey.com/docs/commands/DllCall.htm

Everything works great up until the "NWDSList" call.... Then I get a "access denied" code for the return code, and a "6" for "A_LastError", which translates to a windows system error of "ERROR_INVALID_HANDLE".


if I print the inputs to the call, they seem to be fine??
ie:
ctx, = 1
me, = .CN=USERNAME.OU=CONTEXT.O=CONTEXT
%iterread%, = NO_MORE_ITERATIONS

Which leads me to believe that my issue may be with the handling of the output buffer....
Any ideas???
Any tips/pointers on the inputs for NWDSList/NWDSRead that I should be aware of ???


************************************************************
; initializes NWCallsInit
nwrc :=DllCall("calwin32\NWCallsInit", UInt, 0, UInt, 0 )
If nwrc <> 0
{
MsgBox Error: NWCallsInit was not successful. That's all I know.
Exit
}


; pre-load NetWare netwin32 utility DLL
hModule := DllCall("LoadLibrary", "str", "netwin32.Dll")
if !hModule {
MsgBox Error: Can't load netwin32 DLL. are you SURE the Novell client is on this machine?
Exit
}


; Create new context handle
cCode := DllCall("netwin32.Dll\NWDSCreateContextHandle", "Int*", ctx, "Int")
if cCode <> 0
{
MsgBox Error: NWDSCreateContextHandle was not successful. %cCode%.
Exit
}

; Authenticated ??
cCode := DllCall("netwin32.Dll\NWIsDSAuthenticated", UInt, 0)
if cCode <> 1
{
MsgBox Error: you are not logged in. %cCode%.
Exit
}


; NWDSSetContext -- set context to root
retcode := DllCall("netwin32.Dll\NWDSSetContext", "Int", ctx, "Int", 3, "Int", DS_ROOT_NAME)
;msgbox, %Errorlevel%
If retcode <> 0
{
MsgBox, NWDSSetContext returned error %retcode%
}


;get default DS tree name from our context (root)
VarSetCapacity(DS_ROOT_NAME, 48)
retcode := DllCall("netwin32.Dll\NWDSGetContext", "Int", ctx, "Int", 11, "Str", DS_ROOT_NAME)
If retcode <> 0
{
MsgBox, NWDSGetContext returned error %retcode%
}
; this produces the correct tree name
;msgbox, %DS_ROOT_NAME%


; NWDS who am I.
VarSetCapacity(me, 48)
cCode2 := DllCall("netwin32.Dll\NWDSWhoAmI", "Int", ctx, "Str", me)
if cCode2 <> 0
{
MsgBox Error: NWDSWhoAmI was not successful. %cCode2%.
Exit
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; this prints CN=USERNAME (with context)
;msgbox, %me%

;add leading "." to CN and a CR to the end
me = .%me%`n

msgbox, %me%

MAX_MESSAGE_LEN = 64512
DEFAULT_MESSAGE_LEN = 4096

iterHandle = NO_MORE_ITERATIONS
iterread = NO_MORE_ITERATIONS


; setup inbuf
retcode := DllCall("netwin32.Dll\NWDSAllocBuf", "*UShort", %DEFAULT_MESSAGE_LEN%, "*Int", inBuf)
;msgbox, %Errorlevel%
If retcode <> 0
{
MsgBox, Alloc Buffer inbuf returned error %retcode%
}


; setup outbuf
retcode := DllCall("netwin32.Dll\NWDSAllocBuf", "*UShort", %DEFAULT_MESSAGE_LEN%, "*Int", outBuf)
;msgbox, %Errorlevel%
If retcode <> 0
{
MsgBox, Alloc Buffer outbuf returned error %retcode%
}


; initialize the inBuf
retcode := DllCall("netwin32.Dll\NWDSInitBuf", "Int", ctx, "UInt", DSV_READ, "Int", inBuf)
;msgbox, %Errorlevel%
If retcode <> 0
{
MsgBox, Init Buffer inbuf returned error %retcode%
}


; Write "Group Membership" to the inbuf buffer
retcode := DllCall("netwin32.Dll\NWDSPutAttrName", "Int", ctx, "Int", inBuf, "Str", "Group Membership")
;msgbox, %Errorlevel%
If retcode <> 0
{
MsgBox, Put Attrib Name "Group Membership" returned error %retcode%
}



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; all good until this call.....which produces a windows system ERROR_INVALID_HANDLE error in %A_LastError%

; NWDSlist
retcode := DllCall("netwin32.Dll\NWDSList", "Int", ctx, "Str", me, "Int", %iterread%, "*Int", outBuf)
msgbox, %Errorlevel%
msgbox, %A_LastError%
If retcode <> 0
{
MsgBox, NWDSlist returned error %retcode%
}
**************************************************************************
Labels (1)
0 Likes
4 Replies
Absent Member.
Absent Member.

"SCOTT OWEN" <SOWEN@almaschools.net> wrote:

> Everything works great up until the "NWDSList" call.... Then I get
> a "access denied" code for the return code, and a "6" for
> "A_LastError", which translates to a windows system error of
> "ERROR_INVALID_HANDLE".


The DllCall script shown is printing / displaying three values;
ErrorLevel, LastError and the retcode variable. What was the value in
retcode, specifically?

The return code from the API itself is the only thing being controlled
by Novell code. Neither the ErrorLevel nor the thread last error
(LastError, GetLastError) are set by the Novell XPLAT APIs. They are
perhaps being set by DllCall / AutoHotKey in response to something, or
maybe are just values left over from some other previous call that set
LastError / ErrorLevel.

But since there is an additional layer (AutoHotKey) between your code
and the actual Novell API, it's possible even the return code is being
preemptively set by DllCall without ever actually calling the Novell
API. e.g. If AutoHotKey couldn't convert the script-defined parameter
successfully in preparation for calling the actual API.

If the return code from the Novell API is not zero, it's expected to
be in the range of 0x8800 for local Novell Client errors, 0x8900 for
errors returned from the NCP server, or -1 to -800 for errors from the
eDirectory server. Neither ERROR_ACCESS_DENIED (5) nor
ERROR_INVALID_HANDLE (6 are values returned by the Novell XPLAT APIs.

I don't see the "asterisk as a prefix" within the DllCall examples, so
I'm not positive what "*Int" actually ends up doing. The DllCall
documentation and examples seem to only show use of the asterisk as a
suffix.

That outBuf is treated as ""*Int", outBuf" on both NWDSAllocBuf and
NWDSlist seems suspicious, since NWDSAllocBuf takes the parameter as
"Buf_T * *" (ppBuf_T, pointer to a pointer to a Buf_T structure),
whereas NWDSList takes the parameter as "Buf_T *" (pBuf_T, pointer to
a Buf_T structure). So presumably their DllCall-defined syntax should
not actually be the same for both of those calls.
http://developer.novell.com/documentation//ndslib/nds__enu/data/sdk198.html
http://developer.novell.com/documentation//ndslib/nds__enu/data/sdk2108.html

On a separate note, technically the iteration handle parameter is
INT_PTR rather than INT, but that shouldn't make a practical
difference for you on Windows XP x86 since both pointers and ints are
the same size on that platform.
http://developer.novell.com/documentation/ndslib/nds__enu/data/sdk2108.html

Alan Adams
Novell Client CPR Group
alan.adams@novell.com

Novell
Making IT Work As One
www.novell.com

Upgrade to OES Community
http://www.novell.com/communities/coolsolutions/upgradetooes/
0 Likes
Absent Member.
Absent Member.

Thanks for your time and expertise Alan,

You are correct the "asterisk as a prefix" is incorrect, but appears to do nothing either way...my bad....

I get no return code, but rather the standard windows 0xc00000005 error code for the %ErrorLevel% and a "6" for the %A_LastError%.
The retcode variable is blank.

ie:
iterread = NO_MORE_ITERATIONS
retcode := DllCall("netwin32.Dll\NWDSList", "Int", ctx, "Str", me, "Int*", iterread, "Int*", outBuf)

produces:
A blank retcode, 0xc00000005 error code for the %ErrorLevel%, and a "6" for the %A_LastError%.
I understand that the error level and last error are not "Novell related" but...they were the only information I could gather...so I included them.

For what it's worth.....
changing iterread to a value (-1)
ie: NO_MORE_ITERATIONS represented by a negative integer, not a string.

iterread := -1
retcode := DllCall("netwin32.Dll\NWDSList", "Int", ctx, "Str", me, "Int*", iterread, "Int*", outBuf)

produces:
-632, a "0" and a "6" for retcode, errorlevel and A_lasterror, respectively.

Any way to take a closer look at this and see what's generating the error???

I'll see what I can find out regarding iterread and outBuf both having the same "type".

Thanks again for your time,

-S










>>> Alan Adams<alan.adams@novell.com> 6/7/2011 1:39 PM >>>

"SCOTT OWEN" <SOWEN@almaschools.net> wrote:


> Everything works great up until the "NWDSList" call.... Then I get
> a "access denied" code for the return code, and a "6" for
> "A_LastError", which translates to a windows system error of
> "ERROR_INVALID_HANDLE".


The DllCall script shown is printing / displaying three values;
ErrorLevel, LastError and the retcode variable. What was the value in
retcode, specifically?

The return code from the API itself is the only thing being controlled
by Novell code. Neither the ErrorLevel nor the thread last error
(LastError, GetLastError) are set by the Novell XPLAT APIs. They are
perhaps being set by DllCall / AutoHotKey in response to something, or
maybe are just values left over from some other previous call that set
LastError / ErrorLevel.

But since there is an additional layer (AutoHotKey) between your code
and the actual Novell API, it's possible even the return code is being
preemptively set by DllCall without ever actually calling the Novell
API. e.g. If AutoHotKey couldn't convert the script-defined parameter
successfully in preparation for calling the actual API.

If the return code from the Novell API is not zero, it's expected to
be in the range of 0x8800 for local Novell Client errors, 0x8900 for
errors returned from the NCP server, or -1 to -800 for errors from the
eDirectory server. Neither ERROR_ACCESS_DENIED (5) nor
ERROR_INVALID_HANDLE (6 are values returned by the Novell XPLAT APIs.

I don't see the "asterisk as a prefix" within the DllCall examples, so
I'm not positive what "*Int" actually ends up doing. The DllCall
documentation and examples seem to only show use of the asterisk as a
suffix.

That outBuf is treated as ""*Int", outBuf" on both NWDSAllocBuf and
NWDSlist seems suspicious, since NWDSAllocBuf takes the parameter as
"Buf_T * *" (ppBuf_T, pointer to a pointer to a Buf_T structure),
whereas NWDSList takes the parameter as "Buf_T *" (pBuf_T, pointer to
a Buf_T structure). So presumably their DllCall-defined syntax should
not actually be the same for both of those calls.
http://developer.novell.com/documentation//ndslib/nds__enu/data/sdk198.html
http://developer.novell.com/documentation//ndslib/nds__enu/data/sdk2108.html

On a separate note, technically the iteration handle parameter is
INT_PTR rather than INT, but that shouldn't make a practical
difference for you on Windows XP x86 since both pointers and ints are
the same size on that platform.
http://developer.novell.com/documentation/ndslib/nds__enu/data/sdk2108.html

Alan Adams
Novell Client CPR Group
alan.adams@novell.com

Novell
Making IT Work As One
www.novell.com

Upgrade to OES Community
http://www.novell.com/communities/coolsolutions/upgradetooes/
0 Likes
Absent Member.
Absent Member.

"SCOTT OWEN" <SOWEN@almaschools.net> wrote:

> changing iterread to a value (-1)
> ie: NO_MORE_ITERATIONS represented by a negative integer, not a string.
>
> iterread := -1
> retcode := DllCall("netwin32.Dll\NWDSList", "Int", ctx, "Str", me, "Int*", iterread, "Int*", outBuf)


-632 being ERR_SYSTEM_FAILURE from eDirectory library. The only place
I see ERR_SYSTEM_FAILURE being returned from the eDirectory library is
when its trying to grovel data in the prepared buffer and didn't find
the buffer to be in a sane state.

So I would guess this is still likely to be related to the question of
how DllCall intends for one to distinguish between passing the pointer
to a pointer and the pointer itself for outBuf.

The true problem likely exists on the NWDSAllocBuf parameters, where
you were expecting to /receive/ a pointer to a buffer which had been
allocated by NWDSAllocBuf. How exactly you would handle that
situation with DllCall isn't clear from the documentation and is
something you may need to clarify with them or their user community.

The references to "char * *" seem the closest to perhaps what's
needed, but doesn't make it clear how you should then pass that
received pointer as the actual parameter to NWDSList.

("char" doesn't seem right, because you're not trying to pass a
literal character. "char *" doesn't seem right, because you're trying
to pass the address contained /in/ the outBuf variable, not an address
/to/ the outBuf variable. "char * *" doesn't seem right, because
you're not trying to pass a pointer to a pointer any more like you
were on NWDSAllocBuf.)

Maybe search or ask about examples for how one would call the Windows
API WTSQuerySessionInformation, specifically in relation to the fourth
parameter ppBuffer. That would be how you want to handle outBuf on
NWDSAllocBuf. And then the manner in which you would later pass the
buffer received from WTSQuerySessionInformation to WTSFreeMemory is
the manner in which you want to pass outBuf to NWDSList.

Alan Adams
Novell Client CPR Group
alan.adams@novell.com

Novell
Making IT Work As One
www.novell.com

Upgrade to OES Community
http://www.novell.com/communities/coolsolutions/upgradetooes/
0 Likes
Absent Member.
Absent Member.

Sorry to bring up an old thread again....I had to step away from this for a while....
But...

I'm back 🙂 ....

Here is what I have found out..

here is a good example of using WTSQuerySessionInformation

http://www.autohotkey.com/forum/topic40268.html&highlight=ppbuffer


It look like the use the "UintP", VarPPBuffer, combination to set up the ppBuffer and a
DllCall("wtsapi32\WTSFreeMemory", "Uint", VarPPBuffer) to pass the data....

this makes me think that the following code should work....but ...no joy...
Now it always returns a "-322" which is an "invalid iteration handle was found" error.
At least this time it is a "real" nds error....
Again...I've tried several different ways of passing "iterread = NO_MORE_ITERATIONS"
But always get a return with a -332 (or a -641) in a few instances for the NWDSRead call.

If you still think the issue may be with the buffers, can you suggest any way for me to test/verify that they are getting init'd correctly and that data (group membership) is being written correclty???

*************************************************************************

MAX_MESSAGE_LEN = 64512
DEFAULT_MESSAGE_LEN = 4096

; setup inbuf
retcode := DllCall("netwin32.Dll\NWDSAllocBuf", "UShort*", %DEFAULT_MESSAGE_LEN%, "UIntP", inBuf)
;msgbox, %Errorlevel%
If retcode <> 0
{
MsgBox, Alloc Buffer inbuf returned error %retcode%
}
inBufPTR = %inBuf%


; setup outbuf
retcode := DllCall("netwin32.Dll\NWDSAllocBuf", "UShort*", %DEFAULT_MESSAGE_LEN%, "UIntP", outBuf)
;msgbox, %Errorlevel%
If retcode <> 0
{
MsgBox, Alloc Buffer outbuf returned error %retcode%
}


; initialize the inBuf
VarSetCapacity(inBuf, 64512, 0)
retcode := DllCall("netwin32.Dll\NWDSInitBuf", "Int", ctx, "UInt", 3, "UInt", inBufPTR)
;msgbox, %Errorlevel%
If retcode <> 0
{
MsgBox, Init Buffer inbuf returned error %retcode%
}



; Write "Group Membership" to the inbuf buffer
retcode := DllCall("netwin32.Dll\NWDSPutAttrName", "Int", ctx, "UInt", inBufPTR, "Str", "Group Membership")
;msgbox, %Errorlevel%
If retcode <> 0
{
MsgBox, Put Attrib Name "Group Membership" returned error %retcode%
}

VarSetCapacity(iterread, 64512)
iterread = NO_MORE_ITERATIONS


;Read the attrib values etc from NDS
retcode := DllCall("netwin32.Dll\NWDSRead", "Int", ctx, "Str", me, "UInt", 1, "Int", False, "UIntP", inBuf, "Str *", iterread, "UIntP", outBuf)
msgbox, %Errorlevel%
If retcode <> 0
{
MsgBox, NWDSRead returned error %retcode%
}
;;nwdsread always give a -322 error
******************************************************************






>>> Alan Adams<alan.adams@novell.com> 6/7/2011 5:11 PM >>>

"SCOTT OWEN" <SOWEN@almaschools.net> wrote:


> changing iterread to a value (-1)
> ie: NO_MORE_ITERATIONS represented by a negative integer, not a string.
>
> iterread := -1
> retcode := DllCall("netwin32.Dll\NWDSList", "Int", ctx, "Str", me, "Int*", iterread, "Int*", outBuf)


-632 being ERR_SYSTEM_FAILURE from eDirectory library. The only place
I see ERR_SYSTEM_FAILURE being returned from the eDirectory library is
when its trying to grovel data in the prepared buffer and didn't find
the buffer to be in a sane state.

So I would guess this is still likely to be related to the question of
how DllCall intends for one to distinguish between passing the pointer
to a pointer and the pointer itself for outBuf.

The true problem likely exists on the NWDSAllocBuf parameters, where
you were expecting to /receive/ a pointer to a buffer which had been
allocated by NWDSAllocBuf. How exactly you would handle that
situation with DllCall isn't clear from the documentation and is
something you may need to clarify with them or their user community.

The references to "char * *" seem the closest to perhaps what's
needed, but doesn't make it clear how you should then pass that
received pointer as the actual parameter to NWDSList.

("char" doesn't seem right, because you're not trying to pass a
literal character. "char *" doesn't seem right, because you're trying
to pass the address contained /in/ the outBuf variable, not an address
/to/ the outBuf variable. "char * *" doesn't seem right, because
you're not trying to pass a pointer to a pointer any more like you
were on NWDSAllocBuf.)

Maybe search or ask about examples for how one would call the Windows
API WTSQuerySessionInformation, specifically in relation to the fourth
parameter ppBuffer. That would be how you want to handle outBuf on
NWDSAllocBuf. And then the manner in which you would later pass the
buffer received from WTSQuerySessionInformation to WTSFreeMemory is
the manner in which you want to pass outBuf to NWDSList.

Alan Adams
Novell Client CPR Group
alan.adams@novell.com

Novell
Making IT Work As One
www.novell.com

Upgrade to OES Community
http://www.novell.com/communities/coolsolutions/upgradetooes/
0 Likes
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.