Hi
Having the occasional issue with Application Exceptions on an app created by C11.1.
Messages like these appear.
I cannot reproduce it but a couple of users have it occurring intermittently.
Any clues on how to intercept it?
Thanks
Paul
Hi
Having the occasional issue with Application Exceptions on an app created by C11.1.
Messages like these appear.
I cannot reproduce it but a couple of users have it occurring intermittently.
Any clues on how to intercept it?
Thanks
Paul
Iād recommend shipping your application with the debug build of the clarion runtime (Clarion11\bin\debug\ClaRUN.dll) and building your application with Debug info >= min and āAdd line Number informationā parameter on.
Install the Clarion debugger as the system debugger on the machines that are seeing the issue, you could then examine the memory (locateoffset) when this window appears and you might be able to workout what api call is happening without the source clw, in my experience its usually a pointer error, ie not got the right address(somevar)
or *parameterprototype
. You can drop the source code file in question onto the machine where this happens in case you have a few api calls within the procedure but then you are sharing the code which you might not want to do?
If you have debugview in your code and the machine has internet access you can run debugview from the internet \live.sysinternals.com\tools\Dbgview.exe and then see what the debugoutput string is.
Something to watch out for with some Windows apiās is MS uses Long Pointers (memory addresses) which point/link to other Long Pointers (memory addresses). In the pic, the memory addresses which are highlighted in the red boxes are all LPās to LPās and I cant work out why MS have done it this way.
ConvertSidToStringSidA function (sddl.h) - Win32 apps | Microsoft Docs
[in] Sid
A pointer to the SID structure to be converted.
[out] StringSid
A pointer to a variable that receives a pointer to a null-terminated SID string. To free the returned buffer, call the LocalFree function.
This might also be useful if you want to explore the stack? This is supposedly how Clarion handles its stack, which may be relevant if you are not using Pascal or C as the passing convention, it depends on if this access violation is a windows api call failing and what you prototyped in the module(āsomeapiā).
TopSpeed / Clarion / JPI - x86 calling conventions - Wikipedia
Iāve been debating whether to sell this as an addon, its a template which makes it easy to prototype parameters basically.
The red box is a bug in C11, its the drop down part which should be attached to the Data Type: Byte bit of the template window on the right.
Read this post
Thanks for the replies. Lots of good knowledge there. I will pass it on and see whether it gets us to point B.
Cheers
Paul
I think the two most common sources for those in my experience are (a) trying to access an object that has not yet been instantiated in that context, or (b) failing to return a value from a procedure that is prototyped to return a string.
Iād say that missing/incorrect project defines cause more hair loss than anything else.
(c) Accessing disposed data.
Always check IF NOT object &= NULL THEN
and set object &= NULL
after DISPOSE
. n.b. this last one is already done for you, but i prefer to both in the same code that is responsible for object &= NEW
Neither of those 2 suggestions is necessary.
If you pass a null reference to DISPOSE(), it will ignore it.
When you pass a reference to DISPOSE(), the reference gets nulled.
PROGRAM
StringRef &STRING
MAP
END
CODE
StringRef &= NEW STRING(20)
DISPOSE(StringRef)
MESSAGE(CHOOSE(StringRef &= NULL,'StringRef is now null','StringRef is NOT NULL'))
DISPOSE(StringRef)
MESSAGE('The world did not end, and ' & CHOOSE(StringRef &= NULL,'StringRef is still null after DISPOSE','StringRef is NOT NULL'))
Perhaps Ericās statement was ambiguous and you read it not as intended?
I think it was intended to be read as two separate things:
IF NOT object &= NULL THEN
ie. check object before using it
this is a good idea especially for things like strings where the dispose does not zero the size (and yes I know we have had this conversation lots of times before but it bears repeating)
StringRef &= NEW STRING(20)
DISPOSE(StringRef)
message('after dispose the size is ' & size(StringRef)) ! size still 20
stringRef &= null
message('after setting to null the size is ' & size(StringRef)) ! size now 0
Hi there,
I need to query the SID and then validate it. Would you please share some piece of code of how are you prototyping the LookupAccountNameA?
Thanks!
In the image here https://clarionhub.com/uploads/default/original/2X/0/0a51c7523fbf5475dc663d32adc47e68f0e847f5.png
to get the SID string you have a long pointer (lp) to long pointer (lp) seen in the bottom left field lplp Sid string. This then gives you the pointer/address to lp sid string and that gives you the pointer to the actual Sid string seen in Sid string.
So it goes like this:
lplp sid string
V
lp sid string
V
Sid string
And these are just longs in clarion.
Iād have to dig out my code to lookup any lookupaccountnamea code which if I get time in the next few days i will.
HTH
Iāve had a look for some code, but I cant find the files using the computers Iāve got to use. When I get round to buying one Iāll have another look, but the main point is where you see lplp in some of the apiās these are long pointers to another long pointer which then leads you to the required info.
HTH
Cool, when you find that code, if you can please share it, still donāt get to read the SID.
Thanks
This might help get you started.
I think youāll find two trains of thought for prototyping (pass by reference/pass by value). For LookupAccountNameA , MSDN says this ā¦
BOOL LookupAccountNameA(
[in, optional] LPCSTR lpSystemName,
[in] LPCSTR lpAccountName,
[out, optional] PSID Sid,
[in, out] LPDWORD cbSid,
[out, optional] LPSTR ReferencedDomainName,
[in, out] LPDWORD cchReferencedDomainName,
[out] PSID_NAME_USE peUse
);
I go for the ADDRESS by value method so no RAW *CSTRINGs, like this ā¦
jhLookupAccountNameA(LONG lpszSystemName, |
LONG lpszAccountName,|
LONG lpSID, |
LONG cbSid, |
LONG lpsReferencedDomainName, |
LONG lpcchReferencedDomainName, |
LONG lpPSID_NAME_USE ),PASCAL,Name('LookupAccountNameA')
I declare variables as MSDN describes
szSystemName CSTRING(128)
szAccountName CSTRING(128)
SID STRING(1024)
cbSID LONG
sReferencedDomain STRING(1024)
lpSIDName LONG
dwResult LONG
To do it ācorrectlyā, MSDN describes making the call with ADDRESS values of āzeroā in order to determine the buffer/STRING sizes (then you should create them accordingly) but given than it describes āpointers to buffersā you can just use big STRINGs and call thus ā¦
dwResult = jhLookupAccountName(Address(szSystemName), |
Address(szAccountName), |
Address(SID), |
Address(cbSID),|
Address(sReferenceDomain), |
Address(lpSIDName))
Iām still going through code, apps and sorting out whats what but have a look at this clw, it might be useful, but iirc its populating some of the info seen in this window here:0a51c7523fbf5475dc663d32adc47e68f0e847f5.png (1182Ć581) (clarionhub.com)
And some of this code is work in progress, and Win11 has introduced new changes.
MEMBER('pcWorkTime.clw') ! This is a MEMBER module
MAP
INCLUDE('PCWOR043.INC'),ONCE !Local module procedure declarations
END
LookupUsers PROCEDURE (pManual) ! Declare Procedure
Loc:NetUserInfoID LONG !
Loc:ServerNameAddress LONG !
Loc:level LONG !
Loc:filter LONG !
Loc:bufptr LONG !
Loc:prefmaxlen LONG !
Loc:entriesread LONG !
Loc:totalentries LONG !
Loc:resume_handle LONG !
Loc:NetUserEnumResult LONG !
Loc:Address LONG !
Loc:Address2 LONG !
Loc:NetUserGetInfoFilter LONG !
Loc:NetUserGetInfobufptr LONG !
Loc:NetUserGetInfoResult LONG !
Loc:NetUserGetInfoAddress LONG !
Loc:NetUserGetInfoAddress2 LONG !
Loc:NetAPIResult LONG !
Loc:TotalSeconds ULONG !
Loc:Years ULONG !
Loc:Days ULONG !
Loc:Hours ULONG !
Loc:Mins ULONG !
Loc:Secs ULONG !
Loc:Flags ULONG !
Loc:Auth_Flags ULONG !
Loc:Time LONG !
Loc:Date LONG !
Loc:SidBoolResult BYTE !
Loc:lstrcpyAResult LONG !
Loc:IS_ProcedureName Cstring(256)
Loc:IS_ModuleFilename Cstring(256)
Loc:IS_ThreadNo Long()
Loc:IS_DebugViewCstring Cstring(1024)
Loc:USER_INFO_3 Like(USER_INFO_3) !Everything excuding SID & Internet Stuff
Loc:USER_INFO_23 Like(USER_INFO_23) !Sid
Loc:USER_INFO_24 Like(USER_INFO_24) !Internet Stuff
FilesOpened BYTE(0)
CODE
? DEBUGHOOK(NetUserInfo:Record)
? DEBUGHOOK(NetUserLookup:Record)
!Loc:IS_DebugViewCstring = 'DebugViewTemplate 1st message output - Loc:IS_ProcedureName =LookupUsers, Loc:IS_ModuleFilename =pcWor043, Loc:IS_ThreadNo = ' & Thread()
Loc:IS_DebugViewCstring = 'LookupUsers pcWor043 ' & Thread() &' ' & Format(Today(), @d7) &' '& Format(Clock(), @t8)
Loc:IS_ProcedureName ='LookupUsers'
Loc:IS_ModuleFilename ='pcWor043'
Loc:IS_ThreadNo = Thread()
IS_DebugView(Loc:IS_DebugViewCstring)
DO OpenFiles
DO NetUserEnum
Do CloseFiles
NetUserEnum Routine
Loc:ServerNameAddress = 0 !This Computer
Loc:level = NetUserEnumLevel3
Loc:filter = FILTER_TEMP_DUPLICATE_ACCOUNT + FILTER_NORMAL_ACCOUNT + FILTER_INTERDOMAIN_TRUST_ACCOUNT + FILTER_WORKSTATION_TRUST_ACCOUNT + FILTER_SERVER_TRUST_ACCOUNT
Loc:bufptr = Address(Loc:USER_INFO_3)
Loc:prefmaxlen = Len(Loc:USER_INFO_3)
DO AddNetUserLookup
Loc:entriesread = 0
Loc:totalentries = 0
Loc:resume_handle = 0
Loop
Loc:NetUserEnumResult = IS_NetUserEnum(Loc:ServerNameAddress,Loc:level,Loc:filter,Loc:bufptr,Loc:prefmaxlen,Address(Loc:entriesread),Address(Loc:totalentries),Address(Loc:resume_handle))
IF Loc:NetUserEnumResult = NERR_Success !or Loc:NetUserEnumResult = 234 !ERROR_MORE_DATA
DO NetUserEnumLookupResults
Loc:NetAPIResult = IS_NetApiBufferFree(Loc:bufptr)
IF Loc:NetAPIResult = NERR_Success
Else
RecordError('NetUserEnum NetApiBufferFree 1 Return Value Error:' & Loc:NetAPIResult )
End
Break
ElsIF Loc:NetUserEnumResult = 234 !ERROR_MORE_DATA
DO NetUserEnumLookupResults
Loc:NetAPIResult = IS_NetApiBufferFree(Loc:bufptr)
IF Loc:NetAPIResult = NERR_Success
Else
RecordError('NetUserEnum NetApiBufferFree 2 Return Value Error:' & Loc:NetAPIResult )
End
Else
RecordError('NetUserEnum Return Value Error:' & Loc:NetUserEnumResult &' '& Loc:entriesread &' '& Loc:totalentries &' '& Loc:resume_handle )
Loc:NetAPIResult = IS_NetApiBufferFree(Loc:bufptr)
IF Loc:NetAPIResult = NERR_Success
Else
RecordError('NetUserEnum NetApiBufferFree 3 Return Value Error:' & Loc:NetAPIResult )
End
Break
End
End
AddNetUserLookup Routine
NUL:SessionID = GLO:SessionID
NUL:Date = Today()
NUL:Time = Clock()
NUL:Manual = pManual
NUL:ComputerName = GLO:ComputerName
NUL:Username = GLO:WindowAccountName
NUL:LookupComputerName = GLO:ComputerName
NUL:LookupUser_Info_Type = Loc:level !NetUserEnumLevel3
NUL:DuplicateAccount = 1 !Loc:NUDuplicateAcc
NUL:NormalAccount = 1 !Loc:NUNormalAcc
NUL:InterDomainTrustAccount = 1 !Loc:NUInterDomainTrustAcc
NUL:WorkstationTrustAccount = 1 !Loc:NUWorkStationTrustAcc
NUL:ServerTrustAccount = 1 !Loc:NUServerTrustAcc
IF NOT Access:NetUserLookup.Insert() = Level:Benign
RecordError('NetUserLookup Insert Error:' & ErrorCode() &' '& Error() )
Else
Loc:NetUserInfoID = NUL:NetUserLookupID
End
NetUserEnumLookupResults Routine
peek(Loc:bufptr,Loc:Address)
Loop Loc:entriesread times
!NUI:NetUserInfoID
NUI:NetUserLookupID = Loc:NetUserInfoID !NUL:NetUserLookupID
peek(Loc:Address,NUI:nameAddress) ; DO LookupName
peek(Loc:Address+4,NUI:passwordAddress) ; Do LookupPassword
peek(Loc:Address+8,NUI:password_age_seconds) ; Do LookupPasswordAge !sec !mins !hours !
peek(Loc:Address+12,NUI:privilege) ; Do LookupPrivilege
peek(Loc:Address+16,NUI:home_dirAddress) ; Do LookupHome_Dir
peek(Loc:Address+20,NUI:commentAddress) ; Do LookupCommentAddress
peek(Loc:Address+24,NUI:flags) ; Do LookupFlags
peek(Loc:Address+28,NUI:script_pathAddress) ; Do LookupScript_Path
peek(Loc:Address+32,NUI:auth_flags) ; Do LookupAuth_Flags
peek(Loc:Address+36,NUI:full_nameAddress) ; Do LookupFull_Name
peek(Loc:Address+40,NUI:usr_commentAddress) ; Do LookupUsr_Comment
peek(Loc:Address+44,NUI:parmsAddress) ; Do LookupParms
peek(Loc:Address+48,NUI:workstationsAddress) ; Do LookupWorkstations
peek(Loc:Address+52,NUI:last_logon) ; Do LookupLast_Logon
peek(Loc:Address+56,NUI:last_logoff) ; Do LookupLast_Logoff
peek(Loc:Address+60,NUI:acct_expires) ; Do LookupAcct_Expires
peek(Loc:Address+64,NUI:max_storage) ! Nothing to do
peek(Loc:Address+68,NUI:units_per_week) ! Nothing to do
peek(Loc:Address+72,NUI:logon_hoursAddress) ; Do LookupLogon_Hours
peek(Loc:Address+76,NUI:bad_pw_count) ! Nothing to do Only works on Domain Controllers and Backup Domain Controls
peek(Loc:Address+80,NUI:num_logons) ! Nothing to do
peek(Loc:Address+84,NUI:logon_serverAddress) ; Do LookupLogon_Server
peek(Loc:Address+88,NUI:country_code) ! Nothing to do
peek(Loc:Address+92,NUI:code_page) ! Nothing to do
peek(Loc:Address+96,NUI:user_id) ! Nothing to do
peek(Loc:Address+100,NUI:primary_group_id) ! Nothing to do
peek(Loc:Address+104,NUI:profileAddress) ; Do LookupProfile
peek(Loc:Address+108,NUI:home_dir_driveAddress) ; Do LookupHome_Dir_Drive
peek(Loc:Address+112,NUI:password_expired) ! Nothing to do
Do LookupUser_Info_23 !Get the SID
DO LookupUser_Info_24 !Get the Internet Account Settings From Win8 onwards
IF NOT Access:NetUserInfo.Insert() = Level:Benign
RecordError('NetUserInfo.Insert Error:' & ErrorCode() &' '& Error() )
End
Loc:Address += Len(Loc:USER_INFO_3)
End
LookupName Routine
IF NUI:nameAddress
NUI:nameLen = IS_lstrlenW(NUI:nameAddress)
Clear(NUI:name)
IF NUI:nameLen
UnicodeToAnsi(NUI:nameAddress,Address(NUI:name))
Else
NUI:name = 'Null'
End
Else
NUI:name = 'Null Address'
End
LookupPassword Routine
IF NUI:passwordAddress
NUI:passwordLen = IS_lstrlenW(NUI:passwordAddress)
Clear(NUI:password)
IF NUI:passwordLen
UnicodeToAnsi(NUI:passwordAddress,Address(NUI:password))
Else
NUI:password = 'Null'
End
Else
NUI:password = 'Null Address'
End
LookupPasswordAge Routine
IF NUI:password_age_seconds
Loc:TotalSeconds = NUI:password_age_seconds
Loc:Years = Loc:TotalSeconds / 31536000 !31557600
Loc:TotalSeconds = Loc:TotalSeconds - (Loc:Years * 31536000)
Loc:Days = Loc:TotalSeconds / 86400
Loc:TotalSeconds = Loc:TotalSeconds - (Loc:Days * 86400)
Loc:Hours = Loc:TotalSeconds / 3600
Loc:TotalSeconds = Loc:TotalSeconds - (Loc:Hours * 3600)
Loc:Mins = Loc:TotalSeconds / 60
Loc:TotalSeconds = Loc:TotalSeconds - (Loc:Mins * 60)
Loc:Secs = Loc:TotalSeconds
NUI:Password_Age_Readable = Loc:Years &' Years ' & Loc:Days & ' Days '& Loc:Hours &' Hours '& Loc:Mins &' mins '& Loc:Secs &' seconds'
Else
NUI:Password_Age_Readable = 'Null'
End
LookupPrivilege Routine
Case NUI:privilege
Of 0
NUI:privilege_Readable = 'Guest'
Of 1
NUI:privilege_Readable = 'User'
Of 2
NUI:privilege_Readable = 'Admin'
Else
NUI:privilege_Readable = 'Null'
End
LookupHome_Dir Routine
IF NUI:home_dirAddress
NUI:home_dirLen = IS_lstrlenW(NUI:home_dirAddress)
Clear(NUI:home_dir)
IF NUI:home_dirLen
UnicodeToAnsi(NUI:home_dirAddress,Address(NUI:home_dir))
Else
NUI:home_dir = 'Null'
End
Else
NUI:home_dir = 'Null Address'
End
LookupCommentAddress Routine
IF NUI:commentAddress
NUI:commentLen = IS_lstrlenW(NUI:commentAddress)
Clear(NUI:comment)
IF NUI:commentLen
UnicodeToAnsi(NUI:commentAddress,Address(NUI:comment))
Else
NUI:comment = 'Null'
End
Else
NUI:comment = 'Null Address'
End
LookupFlags Routine
Loc:Flags = NUI:flags
IF Loc:Flags => UF_USE_AES_KEYS !134217728
NUI:flags_Use_AES_Keys = 1
Loc:Flags -= UF_USE_AES_KEYS
End
IF Loc:Flags => UF_PARTIAL_SECRETS_ACCOUNT !67108864
NUI:flags_Partial_Secrets_Account = 1
Loc:Flags -= UF_PARTIAL_SECRETS_ACCOUNT
End
IF Loc:Flags => UF_NO_AUTH_DATA_REQUIRED !33554432
NUI:flags_No_Auth_Data_Rrequired = 1
Loc:Flags -= UF_NO_AUTH_DATA_REQUIRED
End
IF Loc:Flags => UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION !16777216
NUI:flags_Trusted_To_Autheticate_For_Delegation = 1
Loc:Flags -= UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
End
IF Loc:Flags => UF_PASSWORD_EXPIRED !8388608
NUI:flags_Password_Expired = 1
Loc:Flags -= UF_PASSWORD_EXPIRED
End
IF Loc:Flags => UF_DONT_REQUIRE_PREAUTH !4194304
NUI:flags_Dont_Require_PreAuth = 1
Loc:Flags -= UF_DONT_REQUIRE_PREAUTH
End
IF Loc:Flags => UF_USE_DES_KEY_ONLY !2097152
NUI:flags_Use_DES_Key_Only = 1
Loc:Flags -= UF_USE_DES_KEY_ONLY
End
IF Loc:Flags => UF_NOT_DELEGATED !1048576
NUI:flags_Not_Delegated = 1
Loc:Flags -= UF_NOT_DELEGATED
End
IF Loc:Flags => UF_TRUSTED_FOR_DELEGATION !524288
NUI:flags_Trusted_For_Delegation = 1
Loc:Flags -= UF_TRUSTED_FOR_DELEGATION
End
IF Loc:Flags => UF_SMARTCARD_REQUIRED !262144
NUI:flags_Smartcard_Required = 1
Loc:Flags -= UF_SMARTCARD_REQUIRED
End
IF Loc:Flags => UF_MNS_LOGON_ACCOUNT !131072
NUI:flags_MNS_Logon_Account = 1
Loc:Flags -= UF_MNS_LOGON_ACCOUNT
End
IF Loc:Flags => UF_DONT_EXPIRE_PASSWD !65536
NUI:flags_Dont_Expire_Passwd = 1
Loc:Flags -= UF_DONT_EXPIRE_PASSWD
End
IF Loc:Flags => UF_ACCOUNT_TYPE_MASK !15104
NUI:flags_Account_Type_Mask = 1
Loc:Flags -= UF_ACCOUNT_TYPE_MASK
End
IF Loc:Flags => UF_MACHINE_ACCOUNT_MASK !14336
NUI:flags_Machine_Account_Mask = 1
Loc:Flags -= UF_MACHINE_ACCOUNT_MASK
End
IF Loc:Flags => UF_SERVER_TRUST_ACCOUNT !8192
NUI:flags_Server_Trust_Account = 1
Loc:Flags -= UF_SERVER_TRUST_ACCOUNT
End
IF Loc:Flags => UF_WORKSTATION_TRUST_ACCOUNT !4096
NUI:flags_Workstation_Trust_Account = 1
Loc:Flags -= UF_WORKSTATION_TRUST_ACCOUNT
End
IF Loc:Flags => UF_INTERDOMAIN_TRUST_ACCOUNT !2048
NUI:flags_InterDomain_Trust_Account = 1
Loc:Flags -= UF_INTERDOMAIN_TRUST_ACCOUNT
End
IF Loc:Flags => UF_UNDOCUMENTED1024 !Unknown
NUI:flags_Undocumented1024 = 1
Loc:Flags -= 1024
End
IF Loc:Flags => UF_NORMAL_ACCOUNT !512
NUI:flags_Normal_Account = 1
Loc:Flags -= UF_NORMAL_ACCOUNT
End
IF Loc:Flags => UF_TEMP_DUPLICATE_ACCOUNT !256
NUI:flags_Temp_Duplicate_Account = 1
Loc:Flags -= UF_TEMP_DUPLICATE_ACCOUNT
End
IF Loc:Flags => UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED !128
NUI:flags_Encrypted_Text_Password_Allowed = 1
Loc:Flags -= UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED
End
IF Loc:Flags => UF_PASSWD_CANT_CHANGE !64
NUI:flags_Passwd_Cant_Change = 1
Loc:Flags -= UF_PASSWD_CANT_CHANGE
End
IF Loc:Flags => UF_PASSWD_NOTREQD !32
NUI:flags_Passwd_NotReqd = 1
Loc:Flags -= UF_PASSWD_NOTREQD
End
If Loc:Flags => UF_LOCKOUT !16
NUI:flags_Lockout = 1
Loc:Flags -= UF_LOCKOUT
End
IF Loc:Flags => UF_HOMEDIR_REQUIRED !8
NUI:flags_HomeDir_Required = 1
Loc:Flags -= UF_HOMEDIR_REQUIRED
End
IF Loc:Flags => UF_UNDOCUMENTED4 !Unknown
NUI:flags_Undocumented4 = 1
Loc:Flags -= 4
End
IF Loc:Flags => UF_ACCOUNTDISABLE !2
NUI:flags_AccountDisable = 1
Loc:Flags -= UF_ACCOUNTDISABLE
End
IF Loc:Flags => UF_SCRIPT !1
NUI:flags_Script = 1
Loc:Flags -= UF_SCRIPT
End
LookupScript_Path Routine
IF NUI:script_pathAddress
NUI:script_pathLen = IS_lstrlenW(NUI:script_pathAddress)
Clear(NUI:script_path)
IF NUI:script_pathLen
UnicodeToAnsi(NUI:script_pathAddress,Address(NUI:script_path))
Else
NUI:script_path = 'Null'
End
Else
NUI:script_path = 'Null Address'
End
LookupAuth_Flags Routine
Loc:auth_flags = NUI:auth_flags
IF Loc:auth_flags => AF_SETTABLE_BITS
NUI:auth_flags_SETTABLE_BITS = 1
Loc:auth_flags -= AF_SETTABLE_BITS
End
IF Loc:auth_flags => AF_OP_ACCOUNTS
NUI:auth_flags_OP_ACCOUNTS = 1
Loc:auth_flags -= AF_OP_ACCOUNTS
End
IF Loc:auth_flags => AF_OP_SERVER
NUI:auth_flags_OP_SERVER = 1
Loc:auth_flags -= AF_OP_SERVER
End
IF Loc:auth_flags => AF_OP_COMM
NUI:auth_flags_OP_COMM = 1
Loc:auth_flags -= AF_OP_COMM
End
IF Loc:auth_flags => AF_OP_PRINT
NUI:auth_flags_OP_PRINT = 1
Loc:auth_flags -= AF_OP_PRINT
End
LookupFull_Name Routine
IF NUI:full_nameAddress
NUI:full_nameLen = IS_lstrlenW(NUI:full_nameAddress)
Clear(NUI:full_name)
IF NUI:full_nameLen
UnicodeToAnsi(NUI:full_nameAddress,Address(NUI:full_name))
Else
NUI:full_name = 'Null'
End
Else
NUI:full_name = 'Null Address'
End
LookupUsr_Comment Routine
IF NUI:usr_commentAddress
NUI:usr_commentLen = IS_lstrlenW(NUI:usr_commentAddress)
Clear(NUI:usr_comment)
IF NUI:usr_commentLen
UnicodeToAnsi(NUI:usr_commentAddress,Address(NUI:usr_comment))
Else
NUI:usr_comment = 'Null'
End
Else
NUI:usr_comment = 'Null Address'
End
LookupParms Routine
IF NUI:parmsAddress
NUI:parmsLen = IS_lstrlenW(NUI:parmsAddress)
Clear(NUI:parms)
IF NUI:parmsLen
UnicodeToAnsi(NUI:parmsAddress,Address(NUI:parms))
Else
NUI:parms = 'Null'
End
Else
NUI:parms = 'Null Address'
End
LookupWorkstations Routine
IF NUI:workstationsAddress
NUI:workstationsLen = IS_lstrlenW(NUI:workstationsAddress)
Clear(NUI:workstations)
IF NUI:workstationsLen
UnicodeToAnsi(NUI:workstationsAddress,Address(NUI:workstations))
Else
NUI:workstations = 'Null'
End
Else
NUI:workstations = 'Null Address'
End
LookupLast_Logon Routine
IF NUI:last_logon
Loc:TotalSeconds = NUI:last_logon
Loc:Years = Loc:TotalSeconds / 31536000 !31557600
Loc:TotalSeconds = Loc:TotalSeconds - (Loc:Years * 31536000)
Loc:Days = Loc:TotalSeconds / 86400
Loc:TotalSeconds = Loc:TotalSeconds - (Loc:Days * 86400)
Loc:Hours = Loc:TotalSeconds / 3600
Loc:TotalSeconds = Loc:TotalSeconds - (Loc:Hours * 3600)
Loc:Mins = Loc:TotalSeconds / 60
Loc:TotalSeconds = Loc:TotalSeconds - (Loc:Mins * 60)
Loc:Secs = Loc:TotalSeconds
Loc:Date = (Loc:Years * 365) + Loc:Days + Date(1,1,1970)
Loc:Time = (((Loc:Hours * 3600) + (Loc:Mins * 60) + Loc:Secs) * 100) + 1
NUI:last_logon_Readable = Format(Loc:Date,@d17) &' '& Format(Loc:Time,@T8)
Else
NUI:last_logon_Readable = 'Null'
End
LookupLast_Logoff Routine
NUI:last_logoff_Readable = 'Not Used in Windows'
LookupAcct_Expires Routine
IF NUI:acct_expires
Loc:TotalSeconds = NUI:acct_expires
Loc:Years = Loc:TotalSeconds / 31536000 !31557600
Loc:TotalSeconds = Loc:TotalSeconds - (Loc:Years * 31536000)
Loc:Days = Loc:TotalSeconds / 86400
Loc:TotalSeconds = Loc:TotalSeconds - (Loc:Days * 86400)
Loc:Hours = Loc:TotalSeconds / 3600
Loc:TotalSeconds = Loc:TotalSeconds - (Loc:Hours * 3600)
Loc:Mins = Loc:TotalSeconds / 60
Loc:TotalSeconds = Loc:TotalSeconds - (Loc:Mins * 60)
Loc:Secs = Loc:TotalSeconds
Loc:Date = (Loc:Years * 365) + Loc:Days + Date(1,1,1970)
Loc:Time = (((Loc:Hours * 3600) + (Loc:Mins * 60) + Loc:Secs) * 100) + 1
NUI:acct_expires_Readable = Format(Loc:Date,@d17) &' '& Format(Loc:Time,@T8)
Else
NUI:acct_expires_Readable = 'Null'
End
LookupLogon_Hours Routine
NUI:logon_hoursLen = IS_lstrlenW(NUI:logon_hoursAddress)
LookupLogon_Server Routine
IF NUI:logon_serverAddress
NUI:logon_serverLen = IS_lstrlenW(NUI:logon_serverAddress)
Clear(NUI:logon_server)
IF NUI:logon_serverLen
UnicodeToAnsi(NUI:logon_serverAddress,Address(NUI:logon_server))
Else
NUI:logon_server = 'Null'
End
Else
NUI:logon_server = 'Null Address'
End
LookupProfile Routine
IF NUI:profileAddress
NUI:profileLen = IS_lstrlenW(NUI:profileAddress)
Clear(NUI:profile)
IF NUI:profileLen
UnicodeToAnsi(NUI:profileAddress,Address(NUI:profile))
Else
NUI:profile = 'Null'
End
Else
NUI:profile = 'Null Address'
End
LookupHome_Dir_Drive Routine
IF NUI:home_dir_driveAddress
NUI:home_dir_driveLen = IS_lstrlenW(NUI:home_dir_driveAddress)
Clear(NUI:home_dir_drive)
IF NUI:home_dir_driveLen
UnicodeToAnsi(NUI:home_dir_driveAddress,Address(NUI:home_dir_drive))
Else
NUI:home_dir_drive = 'Null'
End
Else
NUI:home_dir_drive = 'Null Address'
End
LookupUser_Info_23 Routine
Loc:NetUserGetInfoFilter = NetUserEnumLevel23
Loc:NetUserGetInfobufptr = Address(Loc:USER_INFO_23)
Loc:NetUserGetInfoResult = IS_NetUserGetInfo(Loc:ServerNameAddress,NUI:nameAddress,Loc:NetUserGetInfoFilter,Loc:NetUserGetInfobufptr)
IF Loc:NetUserGetInfoResult = NERR_Success
peek(Loc:NetUserGetInfobufptr,Loc:NetUserGetInfoAddress)
peek(Loc:NetUserGetInfoAddress+16,Loc:NetUserGetInfoAddress2)
Loc:SidBoolResult = IS_ConvertSidToStringSid(Loc:NetUserGetInfoAddress2,Address(NUI:user_sidAddress)) !Sends the Sid String address to NUI:user_sidAddress
IF Loc:SidBoolResult = 0
RecordError('ConvertSidToStringSid Return Value Error:' & GetLastError() )
NUI:user_sidLen = 0
NUI:user_sid = 'Null'
Else
NUI:user_sidLen = IS_lstrlenA(NUI:user_sidAddress)
Clear(NUI:user_sid)
Loc:lstrcpyAResult = IS_lstrcpyA(address(NUI:user_sid),NUI:user_sidAddress)
IF NOT Loc:lstrcpyAResult
RecordError('lstrcpyA Return Value Error:' & GetLastError() ) !Dont know if GetLastError will work here
End
End
Else
RecordError('NetUserGetInfo 1 Return Value Error:' & Loc:NetUserGetInfoResult )
End
Loc:NetAPIResult = IS_NetApiBufferFree(Loc:NetUserGetInfobufptr)
IF Loc:NetAPIResult = NERR_Success
Else
RecordError('NetUserGetInfo NetApiBufferFree 1 Return Value Error:' & Loc:NetAPIResult )
End
LookupUser_Info_24 Routine
Loc:NetUserGetInfoFilter = NetUserEnumLevel24
Loc:NetUserGetInfobufptr = Address(Loc:USER_INFO_24)
Loc:NetUserGetInfoResult = IS_NetUserGetInfo(Loc:ServerNameAddress,NUI:nameAddress,Loc:NetUserGetInfoFilter,Loc:NetUserGetInfobufptr)
IF Loc:NetUserGetInfoResult = NERR_Success !or Loc:NetUserEnumResult = 234 !ERROR_MORE_DATA
peek(Loc:NetUserGetInfobufptr,Loc:NetUserGetInfoAddress)
peek(Loc:NetUserGetInfoAddress,NUI:internet_identity) !Bool
peek(Loc:NetUserGetInfoAddress+4,NUI:internet_provider_nameAddress)
IF NUI:internet_provider_nameAddress
NUI:internet_provider_nameLen = IS_lstrlenW(NUI:internet_provider_nameAddress)
Clear(NUI:internet_provider_name)
IF NUI:internet_provider_nameLen
UnicodeToAnsi(NUI:internet_provider_nameAddress,Address(NUI:internet_provider_name))
Else
NUI:internet_provider_name = 'Null'
End
Else
NUI:internet_provider_name = 'Null Address'
End
peek(Loc:NetUserGetInfoAddress+8,NUI:internet_principal_nameAddress)
IF NUI:internet_principal_nameAddress
NUI:internet_principal_nameLen = IS_lstrlenW(NUI:internet_principal_nameAddress)
Clear(NUI:internet_principal_name)
IF NUI:internet_principal_nameLen
UnicodeToAnsi(NUI:internet_principal_nameAddress,Address(NUI:internet_principal_name))
Else
NUI:internet_principal_name = 'Null'
End
Else
NUI:internet_principal_name = 'Null Address'
End
Else
RecordError('NetUserGetInfo 2 Return Value Error:' & Loc:NetUserGetInfoResult )
IF Loc:NetUserGetInfoResult = 124
NUI:internet_provider_name = 'Null - Not Supported'
NUI:internet_principal_name = 'Null - Not Supported'
End
End
Loc:NetAPIResult = IS_NetApiBufferFree(Loc:NetUserGetInfobufptr)
IF Loc:NetAPIResult = NERR_Success
Else
RecordError('NetUserGetInfo NetApiBufferFree 2 Return Value Error:' & Loc:NetAPIResult )
End
!--------------------------------------
OpenFiles ROUTINE
Access:NetUserLookup.Open ! Open File referenced in 'Other Files' so need to inform it's FileManager
Access:NetUserLookup.UseFile ! Use File referenced in 'Other Files' so need to inform it's FileManager
Access:NetUserInfo.Open ! Open File referenced in 'Other Files' so need to inform it's FileManager
Access:NetUserInfo.UseFile ! Use File referenced in 'Other Files' so need to inform it's FileManager
FilesOpened = True
!--------------------------------------
CloseFiles ROUTINE
IF FilesOpened THEN
Access:NetUserLookup.Close
Access:NetUserInfo.Close
FilesOpened = False
END
````Preformatted text`