Error while trying to call JetAttachDatabase from ESENT.dll in Golang

95 views Asked by At

I'm trying to play with the "ESENT.dll" library in Golang. Aim is to open an ESEDB file and read some data inside.

According to MSDN, I first have to create an ESE session then attach the ESEDB file with the following functions from the library :

JET_ERR JET_API JetInit( JET_INSTANCE *pinstance);

JET_ERR JET_API JetBeginSession( JET_INSTANCE instance, JET_SESID *psesid, const char *szUserName, const char *szPassword );

JET_ERR JET_API JetAttachDatabase( JET_SESID sesid, const char *szFilename, JET_GRBIT grbit );

So, that's what I tried to do :

package main

import (
    "fmt"
    "os"
    "syscall"
    "unsafe"
)

var (
    esentDLL = syscall.NewLazyDLL("ESENT.dll")
    instance uintptr
    sesid uintptr
)

func main() {

    esedbFilePath, err := syscall.UTF16PtrFromString(".\\SRUDB.dat")
    if err != nil {
        fmt.Println(err.Error())
        os.Exit(1)
    } else {
        fmt.Println("Done")
    }
    initEseSession()
    attachEseDB(esedbFilePath)

}

func initEseSession() {

    JetInit := esentDLL.NewProc("JetInit")
    JetBeginSession := esentDLL.NewProc("JetBeginSession")

    fmt.Print("JetInit call... ")
    rInit, _, _ := JetInit.Call(
        uintptr(unsafe.Pointer(&instance)))

    if rInit != 0 {
        fmt.Println("Error", rInit)
    } else {
        fmt.Println("Done")
    }

    fmt.Print("JetBeginSession call... ")
    rBeginSession, _, _ := JetBeginSession.Call(
        instance,
        uintptr(unsafe.Pointer(&sesid)),
        0,
        0)

    if rBeginSession != 0 {
        fmt.Println("Error", rBeginSession)
    } else {
        fmt.Println("Done")
    }

}

func attachEseDB(esedbFilePath *uint16) {

    JetAttachDatabase := esentDLL.NewProc("JetAttachDatabase")

    fmt.Print("JetAttachDatabase call... ")
    rAttachDatabase, _, _ := JetAttachDatabase.Call(
        sesid,
        uintptr(unsafe.Pointer(&esedbFilePath)),
        0)

    if rAttachDatabase != 0 {
        fmt.Println("Error :", rAttachDatabase)
    } else {
        fmt.Println("Done")
    }

}

But, after JetAttachDatabase call, I have an unspecified error.

JetInit call... Done
JetBeginSession call... Done
JetAttachDatabase call... Error : 4294965485

Could you help me please? Thanks

UPDATE

I made some changes. Error code return by the ESENT.dll is a 'long' type. So I converted the uintptr returned by the function call to a 'int32' type.

Now I got the good error codes.

Plus, I discovered that absolute path for the ESEDB file always return the error "No shuch file".

This issue is solved using relative path.

But now, thats what I have :

Call JetCreateInstance...       Done    : Code 0 (The function succeeded)
Call JetInit...                 Done    : Code 0 (The function succeeded)
Call JetBeginSession...         Done    : Code 0 (The function succeeded)
Call JetAttachDatabase...       Error   : Code -1032 (The file cannot be accessed because the file is locked or in use)
Call JetOpenDatabase...         Error   : Code -1203 (There is no such database)
Call JetGetDatabaseInfo...      Error   : Code -1010 (There is an invalid database ID)
Call JetCloseDatabase...        Error   : Code -1010 (There is an invalid database ID)
Call JetDetachDatabase...       Error   : Code -1203 (There is no such database)
Call JetEndSession...           Done    : Code 0 (The function succeeded)
Call JetTerm...                 Done    : Code 0 (The function succeeded)

I made some tests with other ESEDB files (SRUDB.dat, spartan.edb, WebCacheV01.dat...) but I always got this issue.

ESEDB files were dumped from my own computer and others, after clean shutdown, so I don't understand why I have this issue...

1

There are 1 answers

1
Wild Zyzop On

According to Extensible Storage Engine Error Codes:

A JET_ERR value of zero should be interpreted as success.

A JET_ERR value that is greater than zero should be interpreted as a warning.

A JET_ERR value that is less than zero should be interpreted as an error.

Therefore, the error code must be converted to signed integer:

fmt.Println("Error :", int32(rAttachDatabase))

Then we get error code -1811, which means JET_errFileNotFound (The file was not found.)

It will not be superfluous to check the return value lastErr:

func attachEseDB(esedbFilePath *uint16) {

    JetAttachDatabase := esentDLL.NewProc("JetAttachDatabase")

    fmt.Print("JetAttachDatabase call... ")
    rAttachDatabase, _, err := JetAttachDatabase.Call(
        sesId,
        uintptr(unsafe.Pointer(&esedbFilePath)),
        0)

    if err != nil {
        fmt.Printf("%s ", err)
    }

    if rAttachDatabase != 0 {
        fmt.Println("Error :", int32(rAttachDatabase))
    } else {
        fmt.Println("Done")
    }

}

In my case, the result was:

JetAttachDatabase call... The filename, directory name, or volume label syntax is incorrect. Error : -1811