mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
6533 lines
169 KiB
6533 lines
169 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
scejet.c
|
|
|
|
Abstract:
|
|
|
|
Sce-Jet service APIs
|
|
|
|
Author:
|
|
|
|
Jin Huang (jinhuang) 13-Jan-1997
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "serverp.h"
|
|
#include <io.h>
|
|
|
|
#include <objbase.h>
|
|
#include <initguid.h>
|
|
|
|
#include <crtdbg.h>
|
|
#include <stddef.h>
|
|
#include <atlconv.h>
|
|
#include <atlbase.h>
|
|
|
|
//#define SCEJET_DBG 1
|
|
|
|
//
|
|
// should be controlled by critical section for static variables
|
|
//
|
|
|
|
static JET_INSTANCE JetInstance=0;
|
|
static BOOL JetInited=FALSE;
|
|
extern CRITICAL_SECTION JetSync;
|
|
|
|
|
|
|
|
|
|
#define SCE_JET_CORRUPTION_ERROR(Err) (Err == JET_errDatabaseCorrupted ||\
|
|
Err == JET_errDiskIO ||\
|
|
Err == JET_errReadVerifyFailure ||\
|
|
Err == JET_errBadPageLink ||\
|
|
Err == JET_errDbTimeCorrupted ||\
|
|
Err == JET_errLogFileCorrupt ||\
|
|
Err == JET_errCheckpointCorrupt ||\
|
|
Err == JET_errLogCorruptDuringHardRestore ||\
|
|
Err == JET_errLogCorruptDuringHardRecovery ||\
|
|
Err == JET_errCatalogCorrupted ||\
|
|
Err == JET_errDatabaseDuplicate)
|
|
|
|
DEFINE_GUID(CLSID_SceWriter,0x9cb9311a, 0x6b16, 0x4d5c, 0x85, 0x3e, 0x53, 0x79, 0x81, 0x38, 0xd5, 0x51);
|
|
// 9cb9311a-6b16-4d5c-853e-53798138d551
|
|
|
|
typedef struct _FIND_CONTEXT_ {
|
|
DWORD Length;
|
|
WCHAR Prefix[SCEJET_PREFIX_MAXLEN];
|
|
} SCEJET_FIND_CONTEXT;
|
|
|
|
//
|
|
// each thread has its own FindContext
|
|
//
|
|
SCEJET_FIND_CONTEXT Thread FindContext;
|
|
|
|
|
|
JET_ERR
|
|
SceJetpSeek(
|
|
IN PSCESECTION hSection,
|
|
IN PWSTR LinePrefix,
|
|
IN DWORD PrefixLength,
|
|
IN SCEJET_SEEK_FLAG SeekBit,
|
|
IN BOOL bOkNoMatch
|
|
);
|
|
|
|
JET_ERR
|
|
SceJetpCompareLine(
|
|
IN PSCESECTION hSection,
|
|
IN JET_GRBIT grbit,
|
|
IN PWSTR LinePrefix OPTIONAL,
|
|
IN DWORD PrefixLength,
|
|
OUT INT *Result,
|
|
OUT DWORD *ActualLength OPTIONAL
|
|
);
|
|
|
|
JET_ERR
|
|
SceJetpMakeKey(
|
|
IN JET_SESID SessionID,
|
|
IN JET_TABLEID TableID,
|
|
IN DOUBLE SectionID,
|
|
IN PWSTR LinePrefix,
|
|
IN DWORD PrefixLength
|
|
);
|
|
|
|
JET_ERR
|
|
SceJetpBuildUpperLimit(
|
|
IN PSCESECTION hSection,
|
|
IN PWSTR LinePrefix,
|
|
IN DWORD Len,
|
|
IN BOOL bReserveCase
|
|
);
|
|
|
|
SCESTATUS
|
|
SceJetpGetAvailableSectionID(
|
|
IN PSCECONTEXT cxtProfile,
|
|
OUT DOUBLE *SectionID
|
|
);
|
|
|
|
SCESTATUS
|
|
SceJetpAddAllSections(
|
|
IN PSCECONTEXT cxtProfile
|
|
);
|
|
|
|
SCESTATUS
|
|
SceJetpConfigJetSystem(
|
|
IN JET_INSTANCE *hinstance
|
|
);
|
|
|
|
SCESTATUS
|
|
SceJetpGetValueFromVersion(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN LPSTR TableName,
|
|
IN LPSTR ColumnName,
|
|
OUT LPSTR Value OPTIONAL,
|
|
IN DWORD ValueLen, // number of bytes
|
|
OUT PDWORD pRetLen
|
|
);
|
|
|
|
SCESTATUS
|
|
SceJetpAddGpo(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN JET_TABLEID TableID,
|
|
IN JET_COLUMNID GpoIDColumnID,
|
|
IN PCWSTR Name,
|
|
OUT LONG *pGpoID
|
|
);
|
|
|
|
//
|
|
// Code to handle profile
|
|
//
|
|
SCESTATUS
|
|
SceJetOpenFile(
|
|
IN LPSTR ProfileFileName,
|
|
IN SCEJET_OPEN_TYPE Flags,
|
|
IN DWORD dwTableOptions,
|
|
OUT PSCECONTEXT *cxtProfile
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine opens the profile (database) and outputs the context handle.
|
|
The information returned in the context handle include the Jet session ID,
|
|
Jet database ID, Jet table ID for SCP table, Jet column ID for column
|
|
"Name" and "Value" in the SCP table, and optional information for SAP and
|
|
SMP table.
|
|
|
|
If the context handle passed in contains not NULL information, this routine
|
|
will close all tables and the database in the context (use the same session).
|
|
|
|
The context handle must be freed by LocalFree after its use.
|
|
|
|
A new jet session is created when the context handle is created.
|
|
|
|
Arguments:
|
|
|
|
ProfileFileName - ASCII name of a database (profile)
|
|
|
|
Flags - flags to open the database
|
|
|
|
cxtProfile - the context handle (See SCECONTEXT structure)
|
|
|
|
Return value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
SCESTATUS_PROFILE_NOT_FOUND
|
|
SCESTATUS_ACCESS_DENIED
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_OTHER_ERROR
|
|
|
|
-- */
|
|
{
|
|
JET_ERR JetErr;
|
|
SCESTATUS rc;
|
|
BOOL FreeContext=FALSE;
|
|
JET_GRBIT JetDbFlag;
|
|
DWORD dwScpTable=0;
|
|
|
|
|
|
if ( ProfileFileName == NULL || cxtProfile == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ( *cxtProfile && ScepIsValidContext(*cxtProfile) ) {
|
|
__try {
|
|
//
|
|
// Close previous opened database
|
|
//
|
|
rc = SceJetCloseFile(
|
|
*cxtProfile,
|
|
FALSE,
|
|
FALSE
|
|
);
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
//
|
|
// this is a invalid pointer
|
|
//
|
|
*cxtProfile = NULL;
|
|
}
|
|
}
|
|
|
|
if ( *cxtProfile == NULL ) {
|
|
//
|
|
// no session
|
|
//
|
|
*cxtProfile = (PSCECONTEXT)LocalAlloc( LMEM_ZEROINIT, sizeof(SCECONTEXT));
|
|
if ( *cxtProfile == NULL ) {
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
}
|
|
(*cxtProfile)->Type = 0xFFFFFF02L;
|
|
(*cxtProfile)->JetSessionID = JET_sesidNil;
|
|
(*cxtProfile)->JetDbID = JET_dbidNil;
|
|
(*cxtProfile)->OpenFlag = SCEJET_OPEN_READ_WRITE;
|
|
(*cxtProfile)->JetScpID = JET_tableidNil;
|
|
(*cxtProfile)->JetSapID = JET_tableidNil;
|
|
(*cxtProfile)->JetSmpID = JET_tableidNil;
|
|
(*cxtProfile)->JetTblSecID = JET_tableidNil;
|
|
|
|
FreeContext = TRUE;
|
|
|
|
}
|
|
|
|
//
|
|
// Begin a session
|
|
//
|
|
if ( (*cxtProfile)->JetSessionID == JET_sesidNil ) {
|
|
JetErr = JetBeginSession(
|
|
JetInstance,
|
|
&((*cxtProfile)->JetSessionID),
|
|
NULL,
|
|
NULL
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
|
|
switch (Flags) {
|
|
case SCEJET_OPEN_EXCLUSIVE:
|
|
case SCEJET_OPEN_NOCHECK_VERSION:
|
|
JetDbFlag = 0; // read & write
|
|
// JetDbFlag = JET_bitDbExclusive;
|
|
(*cxtProfile)->OpenFlag = SCEJET_OPEN_EXCLUSIVE;
|
|
break;
|
|
case SCEJET_OPEN_READ_ONLY:
|
|
JetDbFlag = JET_bitDbReadOnly;
|
|
|
|
(*cxtProfile)->OpenFlag = Flags;
|
|
break;
|
|
default:
|
|
JetDbFlag = 0;
|
|
(*cxtProfile)->OpenFlag = SCEJET_OPEN_READ_WRITE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Attach database
|
|
//
|
|
JetErr = JetAttachDatabase(
|
|
(*cxtProfile)->JetSessionID,
|
|
ProfileFileName,
|
|
JetDbFlag
|
|
);
|
|
#ifdef SCEJET_DBG
|
|
printf("Attach database JetErr=%d\n", JetErr);
|
|
#endif
|
|
if ( JetErr == JET_wrnDatabaseAttached )
|
|
JetErr = JET_errSuccess;
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
//
|
|
// Open database
|
|
//
|
|
JetErr = JetOpenDatabase(
|
|
(*cxtProfile)->JetSessionID,
|
|
ProfileFileName,
|
|
NULL,
|
|
&((*cxtProfile)->JetDbID),
|
|
JetDbFlag //JET_bitDbExclusive
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
#ifdef SCEJET_DBG
|
|
printf("Open database %s return code %d (%d) \n", ProfileFileName, rc, JetErr);
|
|
#endif
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
if ( Flags != SCEJET_OPEN_NOCHECK_VERSION ) {
|
|
|
|
//
|
|
// Check database format (for security manager, version#)
|
|
//
|
|
rc = SceJetCheckVersion( *cxtProfile, NULL );
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
#ifdef SCEJET_DBG
|
|
printf("Open: Version check OK\n");
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// Open section table. must be there
|
|
//
|
|
rc = SceJetOpenTable(
|
|
*cxtProfile,
|
|
"SmTblSection",
|
|
SCEJET_TABLE_SECTION,
|
|
Flags,
|
|
NULL
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
//
|
|
// open smp table -- optional
|
|
//
|
|
rc = SceJetOpenTable(
|
|
*cxtProfile,
|
|
"SmTblSmp",
|
|
SCEJET_TABLE_SMP,
|
|
Flags,
|
|
NULL
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
//
|
|
// get the last used merge table (SCP) to open
|
|
// shouldn't fail
|
|
// 1 - SmTblScp 2 - SmTblScp2 0 - no policy merge
|
|
//
|
|
DWORD Actual;
|
|
|
|
rc = SceJetpGetValueFromVersion(
|
|
*cxtProfile,
|
|
"SmTblVersion",
|
|
"LastUsedMergeTable",
|
|
(LPSTR)&dwScpTable,
|
|
4, // number of bytes
|
|
&Actual
|
|
);
|
|
|
|
if ( (dwScpTable != SCEJET_MERGE_TABLE_1) &&
|
|
(dwScpTable != SCEJET_MERGE_TABLE_2) ) {
|
|
|
|
dwScpTable = SCEJET_LOCAL_TABLE;
|
|
}
|
|
|
|
rc = SCESTATUS_SUCCESS;
|
|
(*cxtProfile)->Type &= 0xFFFFFF0FL;
|
|
|
|
if ( dwTableOptions & SCE_TABLE_OPTION_MERGE_POLICY ) {
|
|
//
|
|
// in policy propagation
|
|
//
|
|
if ( ( dwScpTable == SCEJET_MERGE_TABLE_2 ) ) {
|
|
//
|
|
// the second table is already propped
|
|
//
|
|
rc = SceJetOpenTable(
|
|
*cxtProfile,
|
|
"SmTblScp",
|
|
SCEJET_TABLE_SCP,
|
|
Flags,
|
|
NULL
|
|
);
|
|
(*cxtProfile)->Type |= SCEJET_MERGE_TABLE_1;
|
|
|
|
} else {
|
|
rc = SceJetOpenTable(
|
|
*cxtProfile,
|
|
"SmTblScp2",
|
|
SCEJET_TABLE_SCP,
|
|
Flags,
|
|
NULL
|
|
);
|
|
(*cxtProfile)->Type |= SCEJET_MERGE_TABLE_2;
|
|
}
|
|
} else {
|
|
|
|
switch ( dwScpTable ) {
|
|
case SCEJET_MERGE_TABLE_2:
|
|
//
|
|
// the second table
|
|
//
|
|
rc = SceJetOpenTable(
|
|
*cxtProfile,
|
|
"SmTblScp2",
|
|
SCEJET_TABLE_SCP,
|
|
Flags,
|
|
NULL
|
|
);
|
|
break;
|
|
|
|
case SCEJET_MERGE_TABLE_1:
|
|
|
|
rc = SceJetOpenTable(
|
|
*cxtProfile,
|
|
"SmTblScp",
|
|
SCEJET_TABLE_SCP,
|
|
Flags,
|
|
NULL
|
|
);
|
|
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// open SMP table instead, because SCP table doesn't have information
|
|
//
|
|
(*cxtProfile)->JetScpID = (*cxtProfile)->JetSmpID;
|
|
(*cxtProfile)->JetScpSectionID = (*cxtProfile)->JetSmpSectionID;
|
|
(*cxtProfile)->JetScpNameID = (*cxtProfile)->JetSmpNameID;
|
|
(*cxtProfile)->JetScpValueID = (*cxtProfile)->JetSmpValueID;
|
|
(*cxtProfile)->JetScpGpoID = 0;
|
|
|
|
break;
|
|
}
|
|
|
|
(*cxtProfile)->Type |= dwScpTable;
|
|
}
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
if ( dwTableOptions & SCE_TABLE_OPTION_TATTOO ) {
|
|
|
|
rc = SceJetOpenTable(
|
|
*cxtProfile,
|
|
"SmTblTattoo",
|
|
SCEJET_TABLE_TATTOO,
|
|
Flags,
|
|
NULL
|
|
);
|
|
|
|
} else {
|
|
//
|
|
// open sap table -- optional
|
|
//
|
|
rc = SceJetOpenTable(
|
|
*cxtProfile,
|
|
"SmTblSap",
|
|
SCEJET_TABLE_SAP,
|
|
Flags,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
Done:
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
SceJetCloseFile(
|
|
*cxtProfile,
|
|
FALSE,
|
|
FALSE
|
|
);
|
|
|
|
if ( FreeContext == TRUE ) {
|
|
if ( (*cxtProfile)->JetSessionID != JET_sesidNil ) {
|
|
JetEndSession(
|
|
(*cxtProfile)->JetSessionID,
|
|
JET_bitForceSessionClosed
|
|
);
|
|
}
|
|
LocalFree(*cxtProfile);
|
|
*cxtProfile = NULL;
|
|
}
|
|
}
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetCreateFile(
|
|
IN LPSTR ProfileFileName,
|
|
IN SCEJET_CREATE_TYPE Flags,
|
|
IN DWORD dwTableOptions,
|
|
OUT PSCECONTEXT *cxtProfile
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine creates a database (profile) and outputs the context handle.
|
|
See comments in SceJetOpenFile for information contained in the context.
|
|
|
|
If the database name already exists in the system, there are 3 options:
|
|
Flags = SCEJET_OVERWRITE_DUP - the existing database will be erased and
|
|
recreated.
|
|
Flags = SCEJET_OPEN_DUP - the existing database will be opened and
|
|
format is checked
|
|
Flags = SCEJET_OPEN_DUP_EXCLUSIVE - the existing database will be opened
|
|
exclusively.
|
|
Flags = SCEJET_RETURN_ON_DUP - a error code SCESTATUS_FILE_EXIST is returned.
|
|
|
|
When creating the database, only SCP table is created initially. SAP and SMP
|
|
tables will be created when analysis is performed.
|
|
|
|
The context handle must be freed by LocalFree after its use.
|
|
|
|
Arguments:
|
|
|
|
ProfileFileName - ASCII name of a database to create.
|
|
|
|
Flags - This flag is used when there is an duplicate database
|
|
SCEJET_OVERWRITE_DUP
|
|
SCEJET_OPEN_DUP
|
|
SCEJET_OPEN_DUP_EXCLUSIVE
|
|
SCEJET_RETURN_ON_DUP
|
|
|
|
cxtProfile - The context handle
|
|
|
|
Return value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
SCESTATUS_ACCESS_DENIED
|
|
SCESTATUS_PROFILE_NOT_FOUND
|
|
SCESTATUS_OBJECT_EXIST
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_CANT_DELETE
|
|
SCESTATUS_OTHER_ERROR
|
|
|
|
SCESTATUS from SceJetOpenFile
|
|
|
|
-- */
|
|
{
|
|
JET_ERR JetErr;
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
BOOL FreeContext=FALSE;
|
|
DWORD Len;
|
|
FLOAT Version=(FLOAT)1.2;
|
|
JET_TABLEID TableID;
|
|
JET_COLUMNID ColumnID;
|
|
|
|
|
|
if ( ProfileFileName == NULL || cxtProfile == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ( *cxtProfile && ScepIsValidContext(*cxtProfile) ) {
|
|
//
|
|
// Close previous opened database
|
|
//
|
|
rc = SceJetCloseFile(
|
|
*cxtProfile,
|
|
FALSE,
|
|
FALSE
|
|
);
|
|
} else {
|
|
*cxtProfile = NULL;
|
|
}
|
|
|
|
if ( *cxtProfile == NULL ) {
|
|
//
|
|
// no session
|
|
//
|
|
*cxtProfile = (PSCECONTEXT)LocalAlloc( LMEM_ZEROINIT, sizeof(SCECONTEXT));
|
|
if ( *cxtProfile == NULL ) {
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
}
|
|
(*cxtProfile)->Type = 0xFFFFFF02L;
|
|
(*cxtProfile)->JetSessionID = JET_sesidNil;
|
|
(*cxtProfile)->JetDbID = JET_dbidNil;
|
|
(*cxtProfile)->OpenFlag = SCEJET_OPEN_READ_WRITE;
|
|
(*cxtProfile)->JetScpID = JET_tableidNil;
|
|
(*cxtProfile)->JetSapID = JET_tableidNil;
|
|
(*cxtProfile)->JetSmpID = JET_tableidNil;
|
|
(*cxtProfile)->JetTblSecID = JET_tableidNil;
|
|
|
|
FreeContext = TRUE;
|
|
|
|
}
|
|
|
|
(*cxtProfile)->Type &= 0xFFFFFF0FL;
|
|
|
|
//
|
|
// Begin a session
|
|
//
|
|
if ( (*cxtProfile)->JetSessionID == JET_sesidNil ) {
|
|
JetErr = JetBeginSession(
|
|
JetInstance,
|
|
&((*cxtProfile)->JetSessionID),
|
|
NULL,
|
|
NULL
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
//
|
|
// Create database
|
|
//
|
|
JetErr = JetCreateDatabase(
|
|
(*cxtProfile)->JetSessionID,
|
|
ProfileFileName,
|
|
NULL,
|
|
&((*cxtProfile)->JetDbID),
|
|
JET_bitDbExclusive
|
|
);
|
|
if ( JET_errFileNotFound == JetErr ) {
|
|
//
|
|
// if no access to create a file in the path
|
|
// ESENT returns this error. It's fixed in ESE98
|
|
// we have to mask it to access denied error for now
|
|
//
|
|
JetErr = JET_errFileAccessDenied;
|
|
}
|
|
#ifdef SCEJET_DBG
|
|
printf("Create database %s JetErr = %d\n", ProfileFileName, JetErr);
|
|
#endif
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
(*cxtProfile)->OpenFlag = SCEJET_OPEN_EXCLUSIVE;
|
|
|
|
if ( rc == SCESTATUS_OBJECT_EXIST ) {
|
|
switch ( Flags ) {
|
|
case SCEJET_OVERWRITE_DUP:
|
|
//
|
|
// erase the database
|
|
//
|
|
|
|
JetDetachDatabase(
|
|
(*cxtProfile)->JetSessionID,
|
|
ProfileFileName
|
|
);
|
|
|
|
if ( !DeleteFileA(ProfileFileName) &&
|
|
GetLastError() != ERROR_FILE_NOT_FOUND ) {
|
|
|
|
ScepLogOutput3(1,GetLastError(), SCEDLL_ERROR_DELETE_DB );
|
|
}
|
|
|
|
//
|
|
// if delete database failed, log the error but continue to
|
|
// create the database. This call will fail with Jet error.
|
|
//
|
|
JetErr = JetCreateDatabase(
|
|
(*cxtProfile)->JetSessionID,
|
|
ProfileFileName,
|
|
NULL,
|
|
&((*cxtProfile)->JetDbID),
|
|
JET_bitDbExclusive
|
|
);
|
|
if ( JET_errFileNotFound == JetErr ) {
|
|
//
|
|
// if no access to create a file in the path
|
|
// ESENT returns this error. It's fixed in ESE98
|
|
// we have to mask it to access denied error for now
|
|
//
|
|
JetErr = JET_errFileAccessDenied;
|
|
}
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
break;
|
|
|
|
case SCEJET_OPEN_DUP:
|
|
//
|
|
// Open the database
|
|
//
|
|
rc = SceJetOpenFile(
|
|
ProfileFileName,
|
|
SCEJET_OPEN_READ_WRITE,
|
|
dwTableOptions,
|
|
cxtProfile
|
|
);
|
|
goto Done;
|
|
break;
|
|
|
|
case SCEJET_OPEN_DUP_EXCLUSIVE:
|
|
//
|
|
// Open the database
|
|
//
|
|
rc = SceJetOpenFile(
|
|
ProfileFileName,
|
|
SCEJET_OPEN_EXCLUSIVE,
|
|
dwTableOptions,
|
|
cxtProfile
|
|
);
|
|
goto Done;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
#ifdef SCEJET_DBG
|
|
printf("Create/Open database\n");
|
|
#endif
|
|
|
|
//
|
|
// create required tables - SmTblVersion
|
|
//
|
|
|
|
rc = SceJetCreateTable(
|
|
*cxtProfile,
|
|
"SmTblVersion",
|
|
SCEJET_TABLE_VERSION,
|
|
SCEJET_CREATE_IN_BUFFER,
|
|
&TableID,
|
|
&ColumnID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
//
|
|
// insert one record into the version table
|
|
//
|
|
JetErr = JetPrepareUpdate((*cxtProfile)->JetSessionID,
|
|
TableID,
|
|
JET_prepInsert
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// set value "1.2" in "Version" column
|
|
//
|
|
|
|
JetErr = JetSetColumn(
|
|
(*cxtProfile)->JetSessionID,
|
|
TableID,
|
|
ColumnID,
|
|
(void *)&Version,
|
|
4,
|
|
0, //JET_bitSetOverwriteLV,
|
|
NULL
|
|
);
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
//
|
|
// if setting fails, cancel the prepared record
|
|
//
|
|
JetPrepareUpdate( (*cxtProfile)->JetSessionID,
|
|
TableID,
|
|
JET_prepCancel
|
|
);
|
|
} else {
|
|
|
|
//
|
|
// Setting columns succeed. Update the record
|
|
//
|
|
JetErr = JetUpdate( (*cxtProfile)->JetSessionID,
|
|
TableID,
|
|
NULL,
|
|
0,
|
|
&Len
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
}
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
#ifdef SCEJET_DBG
|
|
printf("create version table\n");
|
|
#endif
|
|
//
|
|
// create section table and insert pre-defined sections
|
|
//
|
|
rc = SceJetCreateTable(
|
|
*cxtProfile,
|
|
"SmTblSection",
|
|
SCEJET_TABLE_SECTION,
|
|
SCEJET_CREATE_IN_BUFFER,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
#ifdef SCEJET_DBG
|
|
printf("create section table\n");
|
|
#endif
|
|
|
|
rc = SceJetpAddAllSections(
|
|
*cxtProfile
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
#ifdef SCEJET_DBG
|
|
printf("add sections\n");
|
|
#endif
|
|
|
|
|
|
//
|
|
// create scp table
|
|
//
|
|
rc = SceJetCreateTable(
|
|
*cxtProfile,
|
|
"SmTblScp",
|
|
SCEJET_TABLE_SCP,
|
|
SCEJET_CREATE_IN_BUFFER,
|
|
NULL,
|
|
NULL
|
|
);
|
|
#ifdef SCEJET_DBG
|
|
printf("Create table scp %d\n", rc);
|
|
#endif
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
if ( dwTableOptions & SCE_TABLE_OPTION_MERGE_POLICY ) {
|
|
(*cxtProfile)->Type |= SCEJET_MERGE_TABLE_1;
|
|
} else {
|
|
(*cxtProfile)->Type |= SCEJET_LOCAL_TABLE;
|
|
}
|
|
|
|
//
|
|
// create scp table
|
|
//
|
|
rc = SceJetCreateTable(
|
|
*cxtProfile,
|
|
"SmTblSmp",
|
|
SCEJET_TABLE_SMP,
|
|
SCEJET_CREATE_IN_BUFFER,
|
|
NULL,
|
|
NULL
|
|
);
|
|
#ifdef SCEJET_DBG
|
|
printf("Create table smp %d\n", rc);
|
|
#endif
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
rc = SceJetCreateTable(
|
|
*cxtProfile,
|
|
"SmTblScp2",
|
|
SCEJET_TABLE_SCP,
|
|
SCEJET_CREATE_NO_TABLEID,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
rc = SceJetCreateTable(
|
|
*cxtProfile,
|
|
"SmTblGpo",
|
|
SCEJET_TABLE_GPO,
|
|
SCEJET_CREATE_NO_TABLEID,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
if ( dwTableOptions & SCE_TABLE_OPTION_TATTOO ) {
|
|
rc = SceJetCreateTable(
|
|
*cxtProfile,
|
|
"SmTblTattoo",
|
|
SCEJET_TABLE_TATTOO,
|
|
SCEJET_CREATE_IN_BUFFER,
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
Done:
|
|
|
|
//
|
|
// clearn up if error out
|
|
//
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
|
|
SceJetCloseFile(
|
|
*cxtProfile,
|
|
FALSE,
|
|
FALSE
|
|
);
|
|
if ( FreeContext == TRUE ) {
|
|
if ( (*cxtProfile)->JetSessionID != JET_sesidNil ) {
|
|
JetEndSession(
|
|
(*cxtProfile)->JetSessionID,
|
|
JET_bitForceSessionClosed
|
|
);
|
|
}
|
|
LocalFree(*cxtProfile);
|
|
*cxtProfile = NULL;
|
|
}
|
|
}
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetCloseFile(
|
|
IN PSCECONTEXT hProfile,
|
|
IN BOOL TermSession,
|
|
IN BOOL Terminate
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine closes a context handle, which closes all tables opened in
|
|
the database and then closes the database.
|
|
|
|
Terminate parameter is ignored and Jet engine is not stoppped when this parameter
|
|
is set to TRUE, because there might be other clients using Jet and Jet writer is
|
|
dependent on it.
|
|
|
|
Arguments:
|
|
|
|
hProfile - The context handle
|
|
|
|
Terminate - TRUE = Terminate the Jet session and engine.
|
|
|
|
Return value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
|
|
-- */
|
|
{
|
|
|
|
JET_ERR JetErr;
|
|
|
|
|
|
if ( hProfile == NULL )
|
|
goto Terminate;
|
|
|
|
CHAR szDbName[1025];
|
|
|
|
//
|
|
// Close SCP table if it is opened
|
|
//
|
|
if ( (hProfile->JetScpID != JET_tableidNil) ) {
|
|
|
|
if ( hProfile->JetScpID != hProfile->JetSmpID ) {
|
|
JetErr = JetCloseTable(
|
|
hProfile->JetSessionID,
|
|
hProfile->JetScpID
|
|
);
|
|
}
|
|
hProfile->JetScpID = JET_tableidNil;
|
|
}
|
|
//
|
|
// Close SAP table if it is opened
|
|
//
|
|
if ( hProfile->JetSapID != JET_tableidNil ) {
|
|
JetErr = JetCloseTable(
|
|
hProfile->JetSessionID,
|
|
hProfile->JetSapID
|
|
);
|
|
hProfile->JetSapID = JET_tableidNil;
|
|
}
|
|
//
|
|
// Close SMP table if it is opened
|
|
//
|
|
if ( hProfile->JetSmpID != JET_tableidNil ) {
|
|
JetErr = JetCloseTable(
|
|
hProfile->JetSessionID,
|
|
hProfile->JetSmpID
|
|
);
|
|
hProfile->JetSmpID = JET_tableidNil;
|
|
}
|
|
|
|
//
|
|
// get database name
|
|
// do not care if there is error
|
|
//
|
|
szDbName[0] = '\0';
|
|
szDbName[1024] = '\0';
|
|
|
|
if ( hProfile->JetDbID != JET_dbidNil ) {
|
|
|
|
JetGetDatabaseInfo(hProfile->JetSessionID,
|
|
hProfile->JetDbID,
|
|
(void *)szDbName,
|
|
1024,
|
|
JET_DbInfoFilename
|
|
);
|
|
|
|
//
|
|
// Close the database
|
|
//
|
|
JetErr = JetCloseDatabase(
|
|
hProfile->JetSessionID,
|
|
hProfile->JetDbID,
|
|
0
|
|
);
|
|
hProfile->JetDbID = JET_dbidNil;
|
|
|
|
//
|
|
// should detach the database if the database name is not NULL
|
|
// the database is always attached when it's to open
|
|
// do not care error
|
|
//
|
|
if ( szDbName[0] != '\0' ) {
|
|
JetDetachDatabase(hProfile->JetSessionID, szDbName);
|
|
}
|
|
}
|
|
|
|
if ( TermSession || Terminate ) {
|
|
if ( hProfile->JetSessionID != JET_sesidNil ) {
|
|
|
|
JetEndSession(
|
|
hProfile->JetSessionID,
|
|
JET_bitForceSessionClosed
|
|
);
|
|
hProfile->JetSessionID = JET_sesidNil;
|
|
}
|
|
|
|
hProfile->Type = 0;
|
|
|
|
LocalFree(hProfile);
|
|
}
|
|
|
|
Terminate:
|
|
|
|
/*
|
|
if ( Terminate ) {
|
|
|
|
JetTerm(JetInstance);
|
|
JetInstance = 0;
|
|
JetInited = FALSE;
|
|
|
|
}
|
|
*/
|
|
return(SCESTATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Code to handle sections
|
|
//
|
|
|
|
SCESTATUS
|
|
SceJetOpenSection(
|
|
IN PSCECONTEXT hProfile,
|
|
IN DOUBLE SectionID,
|
|
IN SCEJET_TABLE_TYPE tblType,
|
|
OUT PSCESECTION *hSection
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine saves table and section information in the section context
|
|
handle for other section API's use. SCP, SAP, and SMP tables have the
|
|
same section names. The table type indicates which table this section is
|
|
in.
|
|
|
|
The section context handle must be freed by LocalFree after its use.
|
|
|
|
Arguments:
|
|
|
|
hProfile - The profile context handle
|
|
|
|
SectionID - ID of the section to open
|
|
|
|
tblType - The type of the table for this section
|
|
SCEJET_TABLE_SCP
|
|
SCEJET_TABLE_SAP
|
|
SCEJET_TABLE_SMP
|
|
|
|
hSection - The seciton context handle
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
|
|
-- */
|
|
{
|
|
if ( hProfile == NULL ||
|
|
hSection == NULL ||
|
|
SectionID == (DOUBLE)0 ||
|
|
(tblType != SCEJET_TABLE_SCP &&
|
|
tblType != SCEJET_TABLE_SAP &&
|
|
tblType != SCEJET_TABLE_SMP &&
|
|
tblType != SCEJET_TABLE_TATTOO) )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
if ( hProfile->JetSessionID == JET_sesidNil ||
|
|
hProfile->JetDbID == JET_dbidNil ||
|
|
(tblType == SCEJET_TABLE_SCP && hProfile->JetScpID == JET_tableidNil ) ||
|
|
(tblType == SCEJET_TABLE_SMP && hProfile->JetSmpID == JET_tableidNil ) ||
|
|
(tblType == SCEJET_TABLE_SAP && hProfile->JetSapID == JET_tableidNil ) ||
|
|
(tblType == SCEJET_TABLE_TATTOO && hProfile->JetSapID == JET_tableidNil ) )
|
|
return(SCESTATUS_BAD_FORMAT);
|
|
|
|
|
|
if ( *hSection == NULL ) {
|
|
//
|
|
// Allocate memory
|
|
//
|
|
*hSection = (PSCESECTION)LocalAlloc( (UINT)0, sizeof(SCESECTION));
|
|
if ( *hSection == NULL ) {
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
}
|
|
}
|
|
|
|
(*hSection)->SectionID = SectionID;
|
|
|
|
//
|
|
// assign other info to the section context
|
|
//
|
|
(*hSection)->JetSessionID = hProfile->JetSessionID;
|
|
(*hSection)->JetDbID = hProfile->JetDbID;
|
|
|
|
switch (tblType) {
|
|
case SCEJET_TABLE_SCP:
|
|
(*hSection)->JetTableID = hProfile->JetScpID;
|
|
(*hSection)->JetColumnSectionID = hProfile->JetScpSectionID;
|
|
(*hSection)->JetColumnNameID = hProfile->JetScpNameID;
|
|
(*hSection)->JetColumnValueID = hProfile->JetScpValueID;
|
|
(*hSection)->JetColumnGpoID = hProfile->JetScpGpoID;
|
|
break;
|
|
case SCEJET_TABLE_SAP:
|
|
case SCEJET_TABLE_TATTOO:
|
|
(*hSection)->JetTableID = hProfile->JetSapID;
|
|
(*hSection)->JetColumnSectionID = hProfile->JetSapSectionID;
|
|
(*hSection)->JetColumnNameID = hProfile->JetSapNameID;
|
|
(*hSection)->JetColumnValueID = hProfile->JetSapValueID;
|
|
(*hSection)->JetColumnGpoID = 0;
|
|
break;
|
|
default:
|
|
(*hSection)->JetTableID = hProfile->JetSmpID;
|
|
(*hSection)->JetColumnSectionID = hProfile->JetSmpSectionID;
|
|
(*hSection)->JetColumnNameID = hProfile->JetSmpNameID;
|
|
(*hSection)->JetColumnValueID = hProfile->JetSmpValueID;
|
|
(*hSection)->JetColumnGpoID = 0;
|
|
break;
|
|
}
|
|
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetGetLineCount(
|
|
IN PSCESECTION hSection,
|
|
IN PWSTR LinePrefix OPTIONAL,
|
|
IN BOOL bExactCase,
|
|
OUT DWORD *Count
|
|
)
|
|
/* ++
|
|
Fucntion Description:
|
|
|
|
This routine counts the number of lines matching the LinePrefix (Key)
|
|
in the section. If LinePrefix is NULL, all lines is counted.
|
|
|
|
Arguments:
|
|
|
|
hSection - The context handle for the section.
|
|
|
|
LinePrefix - The whole or partial key to match. If NULL, all lines in the
|
|
section is counted.
|
|
|
|
Count - The output count.
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_OTHER_ERROR
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
JET_ERR JetErr;
|
|
DWORD Len;
|
|
INT Result=0;
|
|
SCEJET_SEEK_FLAG SeekFlag;
|
|
|
|
|
|
if ( hSection == NULL || Count == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
*Count = 0;
|
|
|
|
if ( LinePrefix == NULL ) {
|
|
Len = 0;
|
|
SeekFlag = SCEJET_SEEK_GE;
|
|
} else {
|
|
Len = wcslen(LinePrefix)*sizeof(WCHAR);
|
|
|
|
if ( bExactCase )
|
|
SeekFlag = SCEJET_SEEK_GE;
|
|
else
|
|
SeekFlag = SCEJET_SEEK_GE_NO_CASE;
|
|
}
|
|
|
|
//
|
|
// seek the first occurance
|
|
//
|
|
|
|
rc = SceJetSeek(
|
|
hSection,
|
|
LinePrefix,
|
|
Len,
|
|
SeekFlag
|
|
);
|
|
|
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
// no matching record is found
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// Find the record or the next record
|
|
// Define the upper index range
|
|
//
|
|
if ( Len <= 247 ) {
|
|
|
|
JetErr = SceJetpBuildUpperLimit(
|
|
hSection,
|
|
LinePrefix,
|
|
Len,
|
|
bExactCase
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
//
|
|
// count from the current position to the end of the range
|
|
//
|
|
JetErr = JetIndexRecordCount(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
(unsigned long *)Count,
|
|
(unsigned long)0xFFFFFFFF // maximal count
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
//
|
|
// reset the index range. don't care the error code returned
|
|
//
|
|
JetErr = JetSetIndexRange(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
JET_bitRangeRemove
|
|
);
|
|
|
|
} else {
|
|
//
|
|
// Prefix is longer than 247. The index built does not contan all info
|
|
// loop through each record to count
|
|
//
|
|
do {
|
|
// current record is the same.
|
|
*Count = *Count + 1;
|
|
//
|
|
// move to next record
|
|
//
|
|
JetErr = JetMove(hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
JET_MoveNext,
|
|
0
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
// check the record
|
|
|
|
JetErr = SceJetpCompareLine(
|
|
hSection,
|
|
JET_bitSeekGE,
|
|
LinePrefix,
|
|
Len,
|
|
&Result,
|
|
NULL
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
|
|
} while ( rc == SCESTATUS_SUCCESS && Result == 0 );
|
|
}
|
|
|
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND )
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
|
|
SCESTATUS
|
|
SceJetDelete(
|
|
IN PSCESECTION hSection,
|
|
IN PWSTR LinePrefix,
|
|
IN BOOL bObjectFolder,
|
|
IN SCEJET_DELETE_TYPE Flags
|
|
)
|
|
/* ++
|
|
Fucntion Description:
|
|
|
|
This routine deletes the current record, prefix records, or the whole
|
|
section, depending on the Flags.
|
|
|
|
Arguments:
|
|
|
|
hSection - The context handle of the section
|
|
|
|
LinePrefix - The prefix to start with for the deleted lines. This value
|
|
is only used when Flags is set to SCEJET_DELETE_PARTIAL
|
|
|
|
Flags - Options
|
|
SCEJET_DELETE_SECTION
|
|
SCEJET_DELETE_LINE
|
|
SCEJET_DELETE_PARTIAL
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_ACCESS_DEINED
|
|
SCESTATUS_RECORD_NOT_FOUND
|
|
SCESTATUS_OTHER_ERROR
|
|
|
|
-- */
|
|
{
|
|
JET_ERR JetErr;
|
|
SCESTATUS rc;
|
|
INT Result = 0;
|
|
PWSTR TempPrefix=NULL;
|
|
DWORD Len;
|
|
SCEJET_SEEK_FLAG SeekFlag;
|
|
PWSTR NewPrefix=NULL;
|
|
DOUBLE SectionID;
|
|
DWORD Actual;
|
|
|
|
|
|
if ( hSection == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ( Flags == SCEJET_DELETE_PARTIAL ||
|
|
Flags == SCEJET_DELETE_PARTIAL_NO_CASE ) {
|
|
|
|
if ( LinePrefix == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
Len = wcslen(LinePrefix);
|
|
//
|
|
// delete this node exact match first
|
|
//
|
|
if ( Flags == SCEJET_DELETE_PARTIAL )
|
|
SeekFlag = SCEJET_SEEK_EQ;
|
|
else
|
|
SeekFlag = SCEJET_SEEK_EQ_NO_CASE;
|
|
|
|
rc = SceJetSeek(hSection,
|
|
LinePrefix,
|
|
Len*sizeof(WCHAR),
|
|
SeekFlag
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
|
|
if ( SCESTATUS_RECORD_NOT_FOUND == rc ) {
|
|
rc = SCESTATUS_SUCCESS;
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
if ( bObjectFolder &&
|
|
LinePrefix[Len-1] != L'\\' ) {
|
|
|
|
Len++;
|
|
NewPrefix = (PWSTR)ScepAlloc(0, (Len+1)*sizeof(WCHAR));
|
|
|
|
if ( NewPrefix == NULL ) {
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
}
|
|
wcscpy(NewPrefix, LinePrefix);
|
|
NewPrefix[Len-1] = L'\\';
|
|
}
|
|
|
|
} else {
|
|
return(rc);
|
|
}
|
|
|
|
Len = Len*sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
if ( Flags == SCEJET_DELETE_LINE ||
|
|
Flags == SCEJET_DELETE_LINE_NO_CASE ) {
|
|
if ( LinePrefix == NULL ) {
|
|
//
|
|
// delete current line
|
|
// check the current's sectionID before deleting
|
|
//
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetRetrieveColumn(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
hSection->JetColumnSectionID,
|
|
(void *)&SectionID,
|
|
8,
|
|
&Actual,
|
|
0,
|
|
NULL
|
|
));
|
|
|
|
|
|
if (rc == SCESTATUS_SUCCESS && hSection->SectionID != SectionID)
|
|
rc = SCESTATUS_RECORD_NOT_FOUND;
|
|
|
|
if (rc == SCESTATUS_SUCCESS) {
|
|
JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
|
|
} else {
|
|
if ( Flags == SCEJET_DELETE_LINE )
|
|
SeekFlag = SCEJET_SEEK_EQ;
|
|
else
|
|
SeekFlag = SCEJET_SEEK_EQ_NO_CASE;
|
|
|
|
rc = SceJetSeek(hSection,
|
|
LinePrefix,
|
|
wcslen(LinePrefix)*sizeof(WCHAR),
|
|
SeekFlag
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
if ( Flags == SCEJET_DELETE_SECTION ||
|
|
Flags == SCEJET_DELETE_PARTIAL ||
|
|
Flags == SCEJET_DELETE_PARTIAL_NO_CASE ) {
|
|
|
|
if ( Flags == SCEJET_DELETE_SECTION ) {
|
|
//
|
|
// delete the whole section
|
|
// seek the first line of the section
|
|
//
|
|
TempPrefix = NULL;
|
|
Len = 0;
|
|
SeekFlag = SCEJET_SEEK_GE;
|
|
} else {
|
|
//
|
|
// delete all lines begin with the prefix
|
|
// seek the first line of the prefix
|
|
//
|
|
if ( NewPrefix ) {
|
|
TempPrefix = NewPrefix;
|
|
} else {
|
|
TempPrefix = LinePrefix;
|
|
}
|
|
if ( Flags == SCEJET_DELETE_PARTIAL_NO_CASE )
|
|
SeekFlag = SCEJET_SEEK_GE_NO_CASE;
|
|
else
|
|
SeekFlag = SCEJET_SEEK_GE;
|
|
}
|
|
|
|
rc = SceJetSeek(hSection, TempPrefix, Len, SeekFlag);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
if ( NewPrefix ) {
|
|
ScepFree(NewPrefix);
|
|
}
|
|
return(rc);
|
|
}
|
|
|
|
do {
|
|
|
|
//
|
|
// delete current line
|
|
//
|
|
JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
break;
|
|
|
|
//
|
|
// move cursor to next line
|
|
//
|
|
JetErr = JetMove(hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
JET_MoveNext,
|
|
0
|
|
);
|
|
if ( JetErr == JET_errSuccess ) {
|
|
//
|
|
// compare section ID
|
|
//
|
|
JetErr = SceJetpCompareLine(
|
|
hSection,
|
|
JET_bitSeekGE,
|
|
TempPrefix,
|
|
Len,
|
|
&Result,
|
|
NULL
|
|
);
|
|
|
|
if ( JetErr == JET_errSuccess && Result != 0 )
|
|
JetErr = JET_errRecordNotFound;
|
|
|
|
}
|
|
|
|
if ( JetErr == JET_errRecordDeleted ) {
|
|
//
|
|
// skip the deleted record
|
|
//
|
|
JetErr = JET_errSuccess;
|
|
Result = 0;
|
|
}
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
|
|
} while ( rc == SCESTATUS_SUCCESS && Result == 0 );
|
|
|
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND )
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
if ( NewPrefix ) {
|
|
ScepFree(NewPrefix);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
SCESTATUS
|
|
SceJetDeleteAll(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN LPSTR TblName OPTIONAL,
|
|
IN SCEJET_TABLE_TYPE TblType
|
|
)
|
|
/* ++
|
|
Fucntion Description:
|
|
|
|
This routine deletes everything in the table (specified by name or by type)
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - The context handle of the database
|
|
|
|
TblName - optional table name to delete (if not to use the table id in context)
|
|
|
|
TblType - specify the table type to use the table id in context, ignored
|
|
if TblName is specified.
|
|
|
|
Return Value:
|
|
|
|
-- */
|
|
{
|
|
JET_ERR JetErr;
|
|
SCESTATUS rc;
|
|
|
|
JET_TABLEID tmpTblID;
|
|
|
|
if ( cxtProfile == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ( TblName ) {
|
|
|
|
JetErr = JetOpenTable(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetDbID,
|
|
TblName,
|
|
NULL,
|
|
0,
|
|
0,
|
|
&tmpTblID
|
|
);
|
|
if ( JET_errSuccess != JetErr ) {
|
|
return(SceJetJetErrorToSceStatus(JetErr));
|
|
}
|
|
|
|
} else {
|
|
|
|
switch ( TblType ) {
|
|
case SCEJET_TABLE_SCP:
|
|
tmpTblID = cxtProfile->JetScpID;
|
|
break;
|
|
case SCEJET_TABLE_SMP:
|
|
tmpTblID = cxtProfile->JetSmpID;
|
|
break;
|
|
case SCEJET_TABLE_SAP:
|
|
case SCEJET_TABLE_TATTOO:
|
|
tmpTblID = cxtProfile->JetSapID;
|
|
break;
|
|
case SCEJET_TABLE_SECTION:
|
|
tmpTblID = cxtProfile->JetTblSecID;
|
|
break;
|
|
default:
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
}
|
|
|
|
//
|
|
// move cursor to next line
|
|
//
|
|
JetErr = JetMove(cxtProfile->JetSessionID,
|
|
tmpTblID,
|
|
JET_MoveFirst,
|
|
0
|
|
);
|
|
|
|
while ( JET_errSuccess == JetErr ) {
|
|
|
|
//
|
|
// delete current line
|
|
//
|
|
JetErr = JetDelete(cxtProfile->JetSessionID, tmpTblID);
|
|
|
|
//
|
|
// move cursor to next line
|
|
//
|
|
JetErr = JetMove(cxtProfile->JetSessionID,
|
|
tmpTblID,
|
|
JET_MoveNext,
|
|
0
|
|
);
|
|
|
|
}
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND )
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
if ( TblName ) {
|
|
JetCloseTable(cxtProfile->JetSessionID, tmpTblID);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetCloseSection(
|
|
IN PSCESECTION *hSection,
|
|
IN BOOL DestroySection
|
|
)
|
|
/* ++
|
|
Fucntion Description:
|
|
|
|
Closes a section context handle.
|
|
|
|
Arguments:
|
|
|
|
hSection - The section context handle to close
|
|
|
|
Return Value:
|
|
|
|
SCE_SUCCESS
|
|
|
|
-- */
|
|
{
|
|
if ( hSection == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ( *hSection != NULL ) {
|
|
(*hSection)->JetColumnSectionID = 0;
|
|
(*hSection)->JetColumnNameID = 0;
|
|
(*hSection)->JetColumnValueID = 0;
|
|
|
|
(*hSection)->SectionID = (DOUBLE)0;
|
|
|
|
if ( DestroySection ) {
|
|
ScepFree(*hSection);
|
|
*hSection = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
//
|
|
// Code to handle line
|
|
//
|
|
SCESTATUS
|
|
SceJetGetValue(
|
|
IN PSCESECTION hSection,
|
|
IN SCEJET_FIND_TYPE Flags,
|
|
IN PWSTR LinePrefix OPTIONAL,
|
|
IN PWSTR ActualName OPTIONAL,
|
|
IN DWORD NameBufLen,
|
|
OUT DWORD *RetNameLen OPTIONAL,
|
|
IN PWSTR Value OPTIONAL,
|
|
IN DWORD ValueBufLen,
|
|
OUT DWORD *RetValueLen OPTIONAL
|
|
)
|
|
/* ++
|
|
Fucntion Description:
|
|
|
|
This routine retrieves a line from the opened section or close the
|
|
previous search context. When Flag is SCEJET_EXACT_MATCH, this routine
|
|
returns the exact matched line for LinePrefix (LinePrefix can't be NULL).
|
|
If this routine is used to get multiple lines, a SCEJET_PREFIX_MATCH
|
|
must be used for the Flags when the first time it is called. If LinePrefix
|
|
is NULL, the first line in the section is returned; otherwise, the first
|
|
line matching the prefix is returned. When continous call is made for the
|
|
same prefix, use SCEJET_NEXT_LINE for the Flags. LinePrefix is not used
|
|
for continous calls. When finish with the continuous calls, a
|
|
SCEJET_CLOSE_VALUE must be used to close the search handle context.
|
|
|
|
ActualName and Value contains the actual name and value stored in the
|
|
database for the current line. If these two buffers are not big enough,
|
|
an error will return SCE_BUFFER_TOO_SMALL.
|
|
|
|
Passing NULL for ActualName or Value will return the required length for
|
|
that buffer if the RetLength buffer is not NULL.
|
|
|
|
Arguments:
|
|
|
|
hSection - The context handle of the section
|
|
|
|
LinePrefix - The prefix for the line to start with. This is used only
|
|
when Flags is set to SCEJET_PREFIX_MATCH
|
|
|
|
Flags - Options for the operation
|
|
SCEJET_EXACT_MATCH
|
|
SCEJET_PREFIX_MATCH
|
|
SCEJET_NEXT_LINE
|
|
SCEJET_CLOSE_VALUE
|
|
SCEJET_CURRENT -- get current record's value
|
|
|
|
ActualName - The buffer for column "Name"
|
|
|
|
NameBufLen - The buffer length of ActualName
|
|
|
|
RetNameLen - the required buffer length for "Name" column
|
|
|
|
Value - The buffer for column "Value"
|
|
|
|
ValueBufLen - The buffer length of Value
|
|
|
|
RetValueLen - The required buffer length for "Value" column
|
|
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS if success
|
|
SCESTATUS_RECORD_NOT_FOUND if no more match
|
|
other errors:
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_BUFFER_TOO_SMALL
|
|
SCESTATUS_OTHER_ERROR
|
|
|
|
|
|
-- */
|
|
{
|
|
JET_ERR JetErr;
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
SCESTATUS rc1;
|
|
DWORD Len=0;
|
|
|
|
JET_RETINFO RetInfo;
|
|
WCHAR Buffer[128];
|
|
PVOID pTemp=NULL;
|
|
INT Result=0;
|
|
SCEJET_SEEK_FLAG SeekFlag=SCEJET_SEEK_GT;
|
|
|
|
|
|
if ( hSection == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
if ( Flags == SCEJET_CLOSE_VALUE ) {
|
|
//
|
|
// close the index range
|
|
//
|
|
if ( FindContext.Length > 0 ) {
|
|
memset(FindContext.Prefix, '\0', FindContext.Length);
|
|
FindContext.Length = 0;
|
|
}
|
|
|
|
JetErr = JetSetIndexRange(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
JET_bitRangeRemove
|
|
);
|
|
if ( JetErr != JET_errSuccess &&
|
|
JetErr != JET_errKeyNotMade &&
|
|
JetErr != JET_errNoCurrentRecord ) {
|
|
|
|
return(SceJetJetErrorToSceStatus(JetErr));
|
|
}
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
//
|
|
// when name/value is requested (not NULL), the return length buffer
|
|
// cannot be NULL.
|
|
// both return length buffer cannot be NULL at the same time
|
|
//
|
|
if ( (ActualName != NULL && RetNameLen == NULL) ||
|
|
(Value != NULL && RetValueLen == NULL) ) {
|
|
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
switch ( Flags ) {
|
|
|
|
case SCEJET_EXACT_MATCH:
|
|
case SCEJET_EXACT_MATCH_NO_CASE:
|
|
|
|
if ( LinePrefix == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
Len = wcslen(LinePrefix)*sizeof(WCHAR);
|
|
|
|
if ( Flags == SCEJET_EXACT_MATCH )
|
|
SeekFlag = SCEJET_SEEK_EQ;
|
|
else
|
|
SeekFlag = SCEJET_SEEK_EQ_NO_CASE;
|
|
|
|
rc = SceJetSeek(
|
|
hSection,
|
|
LinePrefix,
|
|
Len,
|
|
SeekFlag
|
|
);
|
|
break;
|
|
|
|
|
|
case SCEJET_PREFIX_MATCH:
|
|
case SCEJET_PREFIX_MATCH_NO_CASE:
|
|
|
|
if ( LinePrefix != NULL ) {
|
|
Len = wcslen(LinePrefix)*sizeof(WCHAR);
|
|
|
|
if ( Len > SCEJET_PREFIX_MAXLEN )
|
|
return(SCESTATUS_PREFIX_OVERFLOW);
|
|
|
|
} else {
|
|
Len = 0;
|
|
}
|
|
|
|
if ( Flags == SCEJET_PREFIX_MATCH )
|
|
SeekFlag = SCEJET_SEEK_GE;
|
|
else
|
|
SeekFlag = SCEJET_SEEK_GE_NO_CASE;
|
|
|
|
rc = SceJetSeek(
|
|
hSection,
|
|
LinePrefix,
|
|
Len,
|
|
SeekFlag
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// remember the find context
|
|
//
|
|
if ( Len > 247 ) {
|
|
//
|
|
// in reality JET doesn't allow keys of more than 255 bytes
|
|
//
|
|
wcsncpy(FindContext.Prefix, LinePrefix, SCEJET_PREFIX_MAXLEN-2);
|
|
|
|
if ( Flags == SCEJET_PREFIX_MATCH_NO_CASE )
|
|
_wcslwr(FindContext.Prefix);
|
|
|
|
FindContext.Length = Len;
|
|
}
|
|
//
|
|
// set the upper range limit
|
|
//
|
|
JetErr = SceJetpBuildUpperLimit(
|
|
hSection,
|
|
LinePrefix,
|
|
Len,
|
|
(Flags == SCEJET_PREFIX_MATCH)
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
break;
|
|
|
|
case SCEJET_NEXT_LINE:
|
|
//
|
|
// Move to next line
|
|
//
|
|
JetErr = JetMove(hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
JET_MoveNext,
|
|
0);
|
|
//
|
|
// compare to the prefix
|
|
//
|
|
if ( JetErr == JET_errSuccess && FindContext.Length > 0 ) {
|
|
|
|
#ifdef SCEJET_DBG
|
|
printf("NextLine: Length is greater than 247\n");
|
|
#endif
|
|
JetErr = SceJetpCompareLine(
|
|
hSection,
|
|
JET_bitSeekGE,
|
|
FindContext.Prefix,
|
|
FindContext.Length,
|
|
&Result,
|
|
NULL
|
|
);
|
|
if ( JetErr == JET_errSuccess && Result != 0 )
|
|
JetErr = JET_errRecordNotFound;
|
|
|
|
}
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// Everything else passed in is treated as the current line
|
|
//
|
|
rc = SCESTATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
//
|
|
// Get this line's value
|
|
//
|
|
RetInfo.ibLongValue = 0;
|
|
RetInfo.itagSequence = 1;
|
|
RetInfo.cbStruct = sizeof(JET_RETINFO);
|
|
|
|
if ( ActualName != NULL || RetNameLen != NULL ) {
|
|
//
|
|
// get name field (long binary)
|
|
// if ActualName is NULL, then get the actual bytes
|
|
//
|
|
if ( ActualName != NULL ) {
|
|
Len = NameBufLen;
|
|
pTemp = (void *)ActualName;
|
|
} else {
|
|
Len = 256;
|
|
pTemp = (void *)Buffer;
|
|
}
|
|
|
|
JetErr = JetRetrieveColumn(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
hSection->JetColumnNameID,
|
|
pTemp,
|
|
Len,
|
|
RetNameLen,
|
|
0,
|
|
&RetInfo
|
|
);
|
|
#ifdef SCEJET_DBG
|
|
printf("\tJetErr=%d, Len=%d, RetNameLen=%d\n", JetErr, Len, *RetNameLen);
|
|
#endif
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_BUFFER_TOO_SMALL ) {
|
|
//
|
|
// if only length is requested, don't care buffer_too_small
|
|
//
|
|
if ( ActualName == NULL )
|
|
rc = SCESTATUS_SUCCESS;
|
|
}
|
|
|
|
if ( rc != SCESTATUS_SUCCESS &&
|
|
rc != SCESTATUS_BUFFER_TOO_SMALL )
|
|
return(rc);
|
|
}
|
|
|
|
if ( Value != NULL || RetValueLen != NULL ) {
|
|
//
|
|
// Get value field
|
|
// if Value is NULL, then get the actual bytes
|
|
//
|
|
|
|
if ( Value != NULL ) {
|
|
Len = ValueBufLen;
|
|
pTemp = (PVOID)Value;
|
|
} else {
|
|
Len = 256;
|
|
pTemp = (PVOID)Buffer;
|
|
}
|
|
|
|
JetErr = JetRetrieveColumn(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
hSection->JetColumnValueID,
|
|
pTemp,
|
|
Len,
|
|
RetValueLen,
|
|
0,
|
|
&RetInfo
|
|
);
|
|
#ifdef SCEJET_DBG
|
|
printf("\tJetErr=%d, Len=%d, RetValueLen=%d\n", JetErr, Len, *RetValueLen);
|
|
#endif
|
|
rc1 = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc1 == SCESTATUS_BUFFER_TOO_SMALL ) {
|
|
//
|
|
// if only length is requested, don't care buffer_too_small
|
|
//
|
|
if ( Value == NULL )
|
|
rc1 = SCESTATUS_SUCCESS;
|
|
}
|
|
|
|
if ( rc1 != SCESTATUS_SUCCESS &&
|
|
rc1 != SCESTATUS_BUFFER_TOO_SMALL )
|
|
return(rc1);
|
|
|
|
//
|
|
// rc is the status from retrieving Name field
|
|
//
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
else
|
|
return(rc1);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetSetLine(
|
|
IN PSCESECTION hSection,
|
|
IN PWSTR Name,
|
|
IN BOOL bReserveCase,
|
|
IN PWSTR Value,
|
|
IN DWORD ValueLen,
|
|
IN LONG GpoID
|
|
)
|
|
/* ++
|
|
Fucntion Description:
|
|
|
|
This routine writes the Name and Value to the section (hSection).
|
|
If a exact matched name is found, overwrite, else insert a new
|
|
record.
|
|
|
|
Arguments:
|
|
|
|
hSection - The context handle of the section
|
|
|
|
Name - The info set to Column "Name"
|
|
|
|
Value - The info set to Column "Value"
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_OTHER_ERROR
|
|
SCESTATUS_ACCESS_DENIED
|
|
SCESTATUS_DATA_OVERFLOW
|
|
|
|
-- */
|
|
{
|
|
JET_ERR JetErr;
|
|
DWORD Len;
|
|
SCESTATUS rc;
|
|
DWORD prep;
|
|
JET_SETINFO SetInfo;
|
|
PWSTR LwrName=NULL;
|
|
|
|
if ( hSection == NULL ||
|
|
Name == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
Len = wcslen(Name)*sizeof(WCHAR);
|
|
|
|
if ( Len <= 0 ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ( bReserveCase ) {
|
|
LwrName = Name;
|
|
|
|
} else {
|
|
//
|
|
// lower cased
|
|
//
|
|
LwrName = (PWSTR)ScepAlloc(0, Len+2);
|
|
if ( LwrName == NULL ) {
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
}
|
|
wcscpy(LwrName, Name);
|
|
LwrName = _wcslwr(LwrName);
|
|
|
|
}
|
|
|
|
SetInfo.cbStruct = sizeof(JET_SETINFO);
|
|
SetInfo.itagSequence = 1;
|
|
SetInfo.ibLongValue = 0;
|
|
|
|
//
|
|
// check to see if the same key name already exists
|
|
//
|
|
JetErr = SceJetpSeek(
|
|
hSection,
|
|
LwrName,
|
|
Len,
|
|
SCEJET_SEEK_EQ,
|
|
FALSE
|
|
);
|
|
|
|
if ( JetErr == JET_errSuccess ||
|
|
JetErr == JET_errRecordNotFound ) {
|
|
if ( JetErr == JET_errSuccess )
|
|
// find a match. overwrite the value
|
|
prep = JET_prepReplace;
|
|
else
|
|
// no match. prepare the record for insertion
|
|
prep = JET_prepInsert;
|
|
|
|
JetErr = JetBeginTransaction(hSection->JetSessionID);
|
|
|
|
if ( JetErr == JET_errSuccess ) {
|
|
JetErr = JetPrepareUpdate(hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
prep
|
|
);
|
|
if ( JetErr != JET_errSuccess ) {
|
|
//
|
|
// rollback the transaction
|
|
//
|
|
JetRollback(hSection->JetSessionID,0);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( JetErr != JET_errSuccess)
|
|
return(SceJetJetErrorToSceStatus(JetErr));
|
|
|
|
|
|
if ( prep == JET_prepInsert ) {
|
|
//
|
|
// set the sectionID column
|
|
//
|
|
JetErr = JetSetColumn(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
hSection->JetColumnSectionID,
|
|
(void *)&(hSection->SectionID),
|
|
8,
|
|
0, //JET_bitSetOverwriteLV,
|
|
NULL
|
|
);
|
|
if ( JetErr == JET_errSuccess ) {
|
|
//
|
|
// set the new key in "Name" column
|
|
//
|
|
JetErr = JetSetColumn(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
hSection->JetColumnNameID,
|
|
(void *)LwrName,
|
|
Len,
|
|
0, //JET_bitSetOverwriteLV,
|
|
&SetInfo
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// set value column
|
|
//
|
|
|
|
JetErr = JetSetColumn(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
hSection->JetColumnValueID,
|
|
(void *)Value,
|
|
ValueLen,
|
|
0, //JET_bitSetOverwriteLV,
|
|
&SetInfo
|
|
);
|
|
if ( JetErr == JET_errSuccess ) {
|
|
//
|
|
// if GPO ID is provided and there is a GPOID column, set it
|
|
//
|
|
if ( GpoID > 0 && hSection->JetColumnGpoID > 0 ) {
|
|
|
|
JetErr = JetSetColumn(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
hSection->JetColumnGpoID,
|
|
(void *)&GpoID,
|
|
sizeof(LONG),
|
|
0,
|
|
NULL
|
|
);
|
|
if ( JET_errColumnNotUpdatable == JetErr ) {
|
|
JetErr = JET_errSuccess;
|
|
}
|
|
}
|
|
// else
|
|
// if can't find the column, ignore the error
|
|
//
|
|
|
|
if ( JET_errSuccess == JetErr ) {
|
|
|
|
//
|
|
// Setting columns succeed. Update the record
|
|
//
|
|
JetErr = JetUpdate(hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
NULL,
|
|
0,
|
|
&Len
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS )
|
|
JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
//
|
|
// if setting fails, cancel the prepared record
|
|
//
|
|
JetPrepareUpdate(hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
JET_prepCancel
|
|
);
|
|
//
|
|
// Rollback the transaction
|
|
//
|
|
JetRollback(hSection->JetSessionID,0);
|
|
|
|
}
|
|
|
|
if ( LwrName != Name ) {
|
|
ScepFree(LwrName);
|
|
}
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Exported helper APIs
|
|
//
|
|
SCESTATUS
|
|
SceJetCreateTable(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN LPSTR tblName,
|
|
IN SCEJET_TABLE_TYPE tblType,
|
|
IN SCEJET_CREATE_FLAG nFlags,
|
|
OUT JET_TABLEID *TableID OPTIONAL,
|
|
OUT JET_COLUMNID *ColumnID OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine creates a table in the database opened in the context handle.
|
|
SCP/SAP/SMP tables created in the database have 3 columns: Section, Name,
|
|
and Value, with one index "SectionKey" which is Section+Name ascending.
|
|
Version table has only one column "Version".
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - The context handle
|
|
|
|
tblName - ASCII name of the table to create
|
|
|
|
tblType - The type of the table. It may be one of the following
|
|
SCEJET_TABLE_SCP
|
|
SCEJET_TABLE_SAP
|
|
SCEJET_TABLE_SMP
|
|
SCEJET_TABLE_VERSION
|
|
SCEJET_TABLE_SECTION
|
|
SCEJET_TABLE_TATTOO
|
|
SCEJET_TABLE_GPO
|
|
|
|
TableID - SmTblVersion table id when tblType = SCEJET_TABLE_VERSION.
|
|
|
|
ColumnID - The column ID for Version when tblType = SCEJET_TABLE_VERSION
|
|
|
|
Return value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_OBJECT_EXIST
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_OTHER_ERROR
|
|
|
|
|
|
-- */
|
|
{
|
|
JET_ERR JetErr;
|
|
SCESTATUS rc;
|
|
JET_TABLECREATE TableCreate;
|
|
JET_COLUMNCREATE ColumnCreate[5];
|
|
JET_INDEXCREATE IndexCreate[2];
|
|
DWORD numColumns;
|
|
|
|
|
|
if ( cxtProfile == NULL || tblName == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ( TableID ) {
|
|
*TableID = JET_tableidNil;
|
|
}
|
|
|
|
if ( ColumnID ) {
|
|
*ColumnID = 0;
|
|
}
|
|
|
|
switch ( tblType ) {
|
|
case SCEJET_TABLE_VERSION:
|
|
|
|
if ( TableID == NULL || ColumnID == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
//
|
|
// There is only one column in this table
|
|
//
|
|
ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
|
|
ColumnCreate[0].szColumnName = "Version";
|
|
ColumnCreate[0].coltyp = JET_coltypIEEESingle;
|
|
ColumnCreate[0].cbMax = 4;
|
|
ColumnCreate[0].grbit = JET_bitColumnNotNULL;
|
|
ColumnCreate[0].pvDefault = NULL;
|
|
ColumnCreate[0].cbDefault = 0;
|
|
ColumnCreate[0].cp = 0;
|
|
ColumnCreate[0].columnid = 0;
|
|
|
|
ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
|
|
ColumnCreate[1].szColumnName = "AnalyzeTimeStamp";
|
|
ColumnCreate[1].coltyp = JET_coltypBinary;
|
|
ColumnCreate[1].cbMax = 16; // should be 8 bytes - change later
|
|
ColumnCreate[1].grbit = 0;
|
|
ColumnCreate[1].pvDefault = NULL;
|
|
ColumnCreate[1].cbDefault = 0;
|
|
ColumnCreate[1].cp = 0;
|
|
ColumnCreate[1].columnid = 0;
|
|
|
|
ColumnCreate[2].cbStruct = sizeof(JET_COLUMNCREATE);
|
|
ColumnCreate[2].szColumnName = "ConfigTimeStamp";
|
|
ColumnCreate[2].coltyp = JET_coltypBinary;
|
|
ColumnCreate[2].cbMax = 16; // should be 8 bytes - change later
|
|
ColumnCreate[2].grbit = 0;
|
|
ColumnCreate[2].pvDefault = NULL;
|
|
ColumnCreate[2].cbDefault = 0;
|
|
ColumnCreate[2].cp = 0;
|
|
ColumnCreate[2].columnid = 0;
|
|
|
|
ColumnCreate[3].cbStruct = sizeof(JET_COLUMNCREATE);
|
|
ColumnCreate[3].szColumnName = "LastUsedMergeTable";
|
|
ColumnCreate[3].coltyp = JET_coltypLong;
|
|
ColumnCreate[3].cbMax = 4;
|
|
ColumnCreate[3].grbit = 0;
|
|
ColumnCreate[3].pvDefault = NULL;
|
|
ColumnCreate[3].cbDefault = 0;
|
|
ColumnCreate[3].cp = 0;
|
|
ColumnCreate[3].columnid = 0;
|
|
|
|
ColumnCreate[4].cbStruct = sizeof(JET_COLUMNCREATE);
|
|
ColumnCreate[4].szColumnName = "ProfileDescription";
|
|
ColumnCreate[4].coltyp = JET_coltypLongBinary;
|
|
ColumnCreate[4].cbMax = 1024;
|
|
ColumnCreate[4].grbit = 0;
|
|
ColumnCreate[4].pvDefault = NULL;
|
|
ColumnCreate[4].cbDefault = 0;
|
|
ColumnCreate[4].cp = 0;
|
|
ColumnCreate[4].columnid = 0;
|
|
|
|
//
|
|
// Assign table info
|
|
//
|
|
TableCreate.cbStruct = sizeof(JET_TABLECREATE);
|
|
TableCreate.szTableName = tblName;
|
|
TableCreate.szTemplateTableName = NULL;
|
|
TableCreate.ulPages = 1;
|
|
TableCreate.ulDensity = 90;
|
|
TableCreate.rgcolumncreate = ColumnCreate;
|
|
TableCreate.cColumns = 5;
|
|
TableCreate.rgindexcreate = NULL;
|
|
TableCreate.cIndexes = 0;
|
|
TableCreate.grbit = 0;
|
|
TableCreate.tableid = 0;
|
|
|
|
break;
|
|
|
|
case SCEJET_TABLE_SCP:
|
|
case SCEJET_TABLE_SAP:
|
|
case SCEJET_TABLE_SMP:
|
|
case SCEJET_TABLE_TATTOO:
|
|
|
|
//
|
|
// There are 3 columns in each table.
|
|
// Assign each column info
|
|
//
|
|
ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
|
|
ColumnCreate[0].szColumnName = "SectionID";
|
|
ColumnCreate[0].coltyp = JET_coltypIEEEDouble;
|
|
ColumnCreate[0].cbMax = 8;
|
|
ColumnCreate[0].grbit = JET_bitColumnNotNULL;
|
|
ColumnCreate[0].pvDefault = NULL;
|
|
ColumnCreate[0].cbDefault = 0;
|
|
ColumnCreate[0].cp = 0;
|
|
ColumnCreate[0].columnid = 0;
|
|
|
|
ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
|
|
ColumnCreate[1].szColumnName = "Name";
|
|
ColumnCreate[1].coltyp = JET_coltypLongBinary;
|
|
ColumnCreate[1].cbMax = 1024;
|
|
ColumnCreate[1].grbit = 0; //JET_bitColumnNotNULL;
|
|
ColumnCreate[1].pvDefault = NULL;
|
|
ColumnCreate[1].cbDefault = 0;
|
|
ColumnCreate[1].cp = 0;
|
|
ColumnCreate[1].columnid = 0;
|
|
|
|
ColumnCreate[2].cbStruct = sizeof(JET_COLUMNCREATE);
|
|
ColumnCreate[2].szColumnName = "Value";
|
|
ColumnCreate[2].coltyp = JET_coltypLongBinary;
|
|
ColumnCreate[2].cbMax = (unsigned long)0x7FFFFFFF; // 2GB
|
|
ColumnCreate[2].grbit = 0;
|
|
ColumnCreate[2].pvDefault = NULL;
|
|
ColumnCreate[2].cbDefault = 0;
|
|
ColumnCreate[2].cp = 0;
|
|
ColumnCreate[2].columnid = 0;
|
|
|
|
numColumns = 3;
|
|
|
|
if ( tblType == SCEJET_TABLE_SCP ) {
|
|
|
|
ColumnCreate[3].cbStruct = sizeof(JET_COLUMNCREATE);
|
|
ColumnCreate[3].szColumnName = "GpoID";
|
|
ColumnCreate[3].coltyp = JET_coltypLong;
|
|
ColumnCreate[3].cbMax = 4;
|
|
ColumnCreate[3].grbit = 0;
|
|
ColumnCreate[3].pvDefault = NULL;
|
|
ColumnCreate[3].cbDefault = 0;
|
|
ColumnCreate[3].cp = 0;
|
|
ColumnCreate[3].columnid = 0;
|
|
|
|
numColumns = 4;
|
|
}
|
|
|
|
//
|
|
// Assign index info - one index in each table.
|
|
//
|
|
memset(IndexCreate, 0, sizeof(JET_INDEXCREATE) );
|
|
IndexCreate[0].cbStruct = sizeof(JET_INDEXCREATE);
|
|
IndexCreate[0].szIndexName = "SectionKey";
|
|
IndexCreate[0].szKey = "+SectionID\0+Name\0\0";
|
|
IndexCreate[0].cbKey = 18;
|
|
IndexCreate[0].grbit = 0; // JET_bitIndexPrimary; // | JET_bitIndexUnique;
|
|
IndexCreate[0].ulDensity = 50;
|
|
//
|
|
// Assign table info
|
|
//
|
|
TableCreate.cbStruct = sizeof(JET_TABLECREATE);
|
|
TableCreate.szTableName = tblName;
|
|
TableCreate.szTemplateTableName = NULL;
|
|
TableCreate.ulPages = 20;
|
|
TableCreate.ulDensity = 50;
|
|
TableCreate.rgcolumncreate = ColumnCreate;
|
|
TableCreate.cColumns = numColumns;
|
|
TableCreate.rgindexcreate = IndexCreate;
|
|
TableCreate.cIndexes = 1;
|
|
TableCreate.grbit = 0;
|
|
TableCreate.tableid = 0;
|
|
|
|
break;
|
|
|
|
case SCEJET_TABLE_SECTION:
|
|
//
|
|
// There are 2 columns in this table.
|
|
// Assign each column info
|
|
//
|
|
ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
|
|
ColumnCreate[0].szColumnName = "SectionID";
|
|
ColumnCreate[0].coltyp = JET_coltypIEEEDouble;
|
|
ColumnCreate[0].cbMax = 8;
|
|
ColumnCreate[0].grbit = JET_bitColumnNotNULL;
|
|
ColumnCreate[0].pvDefault = NULL;
|
|
ColumnCreate[0].cbDefault = 0;
|
|
ColumnCreate[0].cp = 0;
|
|
ColumnCreate[0].columnid = 0;
|
|
|
|
ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
|
|
ColumnCreate[1].szColumnName = "Name";
|
|
ColumnCreate[1].coltyp = JET_coltypBinary;
|
|
ColumnCreate[1].cbMax = 255;
|
|
ColumnCreate[1].grbit = JET_bitColumnNotNULL;
|
|
ColumnCreate[1].pvDefault = NULL;
|
|
ColumnCreate[1].cbDefault = 0;
|
|
ColumnCreate[1].cp = 0;
|
|
ColumnCreate[1].columnid = 0;
|
|
|
|
//
|
|
// Assign index info - one index in each table.
|
|
//
|
|
memset(IndexCreate, 0, 2*sizeof(JET_INDEXCREATE) );
|
|
IndexCreate[0].cbStruct = sizeof(JET_INDEXCREATE);
|
|
IndexCreate[0].szIndexName = "SectionKey";
|
|
IndexCreate[0].szKey = "+Name\0\0";
|
|
IndexCreate[0].cbKey = 7;
|
|
IndexCreate[0].grbit = JET_bitIndexPrimary; // | JET_bitIndexUnique;
|
|
IndexCreate[0].ulDensity = 80;
|
|
|
|
IndexCreate[1].cbStruct = sizeof(JET_INDEXCREATE);
|
|
IndexCreate[1].szIndexName = "SecID";
|
|
IndexCreate[1].szKey = "+SectionID\0\0";
|
|
IndexCreate[1].cbKey = 12;
|
|
IndexCreate[1].grbit = 0;
|
|
IndexCreate[1].ulDensity = 80;
|
|
//
|
|
// Assign table info
|
|
//
|
|
TableCreate.cbStruct = sizeof(JET_TABLECREATE);
|
|
TableCreate.szTableName = tblName;
|
|
TableCreate.szTemplateTableName = NULL;
|
|
TableCreate.ulPages = 10;
|
|
TableCreate.ulDensity = 80;
|
|
TableCreate.rgcolumncreate = ColumnCreate;
|
|
TableCreate.cColumns = 2;
|
|
TableCreate.rgindexcreate = IndexCreate;
|
|
TableCreate.cIndexes = 2;
|
|
TableCreate.grbit = 0;
|
|
TableCreate.tableid = 0;
|
|
|
|
break;
|
|
|
|
case SCEJET_TABLE_GPO:
|
|
//
|
|
// There are 3 columns in this table.
|
|
// Assign each column info
|
|
//
|
|
ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
|
|
ColumnCreate[0].szColumnName = "GpoID";
|
|
ColumnCreate[0].coltyp = JET_coltypLong;
|
|
ColumnCreate[0].cbMax = 4;
|
|
ColumnCreate[0].grbit = JET_bitColumnNotNULL;
|
|
ColumnCreate[0].pvDefault = NULL;
|
|
ColumnCreate[0].cbDefault = 0;
|
|
ColumnCreate[0].cp = 0;
|
|
ColumnCreate[0].columnid = 0;
|
|
|
|
ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
|
|
ColumnCreate[1].szColumnName = "Name";
|
|
ColumnCreate[1].coltyp = JET_coltypBinary;
|
|
ColumnCreate[1].cbMax = 255;
|
|
ColumnCreate[1].grbit = JET_bitColumnNotNULL;
|
|
ColumnCreate[1].pvDefault = NULL;
|
|
ColumnCreate[1].cbDefault = 0;
|
|
ColumnCreate[1].cp = 0;
|
|
ColumnCreate[1].columnid = 0;
|
|
|
|
ColumnCreate[2].cbStruct = sizeof(JET_COLUMNCREATE);
|
|
ColumnCreate[2].szColumnName = "DisplayName";
|
|
ColumnCreate[2].coltyp = JET_coltypBinary;
|
|
ColumnCreate[2].cbMax = 255;
|
|
ColumnCreate[2].grbit = 0;
|
|
ColumnCreate[2].pvDefault = NULL;
|
|
ColumnCreate[2].cbDefault = 0;
|
|
ColumnCreate[2].cp = 0;
|
|
ColumnCreate[2].columnid = 0;
|
|
|
|
//
|
|
// Assign index info - one index in each table.
|
|
//
|
|
memset(IndexCreate, 0, 2*sizeof(JET_INDEXCREATE) );
|
|
IndexCreate[0].cbStruct = sizeof(JET_INDEXCREATE);
|
|
IndexCreate[0].szIndexName = "SectionKey";
|
|
IndexCreate[0].szKey = "+GpoID\0\0";
|
|
IndexCreate[0].cbKey = 8;
|
|
IndexCreate[0].grbit = JET_bitIndexPrimary; // | JET_bitIndexUnique;
|
|
IndexCreate[0].ulDensity = 80;
|
|
|
|
IndexCreate[1].cbStruct = sizeof(JET_INDEXCREATE);
|
|
IndexCreate[1].szIndexName = "GpoName";
|
|
IndexCreate[1].szKey = "+Name\0\0";
|
|
IndexCreate[1].cbKey = 7;
|
|
IndexCreate[1].grbit = 0;
|
|
IndexCreate[1].ulDensity = 80;
|
|
|
|
//
|
|
// Assign table info
|
|
//
|
|
TableCreate.cbStruct = sizeof(JET_TABLECREATE);
|
|
TableCreate.szTableName = tblName;
|
|
TableCreate.szTemplateTableName = NULL;
|
|
TableCreate.ulPages = 10;
|
|
TableCreate.ulDensity = 80;
|
|
TableCreate.rgcolumncreate = ColumnCreate;
|
|
TableCreate.cColumns = 3;
|
|
TableCreate.rgindexcreate = IndexCreate;
|
|
TableCreate.cIndexes = 2;
|
|
TableCreate.grbit = 0;
|
|
TableCreate.tableid = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// Create the table, column, and index together
|
|
//
|
|
JetErr = JetCreateTableColumnIndex(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetDbID,
|
|
&TableCreate
|
|
);
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( SCESTATUS_OBJECT_EXIST == rc &&
|
|
TableCreate.tableid != JET_tableidNil ) {
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
} else if ( rc == SCESTATUS_SUCCESS &&
|
|
TableCreate.tableid == JET_tableidNil ) {
|
|
|
|
rc = SCESTATUS_OTHER_ERROR;
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// Save the tableid and columnid in the context
|
|
//
|
|
if ( SCEJET_CREATE_NO_TABLEID == nFlags ) {
|
|
//
|
|
// do not need table ID to be returned
|
|
//
|
|
if ( TableCreate.tableid != JET_tableidNil ) {
|
|
JetCloseTable(
|
|
cxtProfile->JetSessionID,
|
|
TableCreate.tableid
|
|
);
|
|
}
|
|
|
|
} else {
|
|
|
|
if ( tblType == SCEJET_TABLE_VERSION ) {
|
|
|
|
*TableID = TableCreate.tableid;
|
|
*ColumnID = ColumnCreate[0].columnid;
|
|
|
|
} else if ( TableID ) {
|
|
*TableID = TableCreate.tableid;
|
|
|
|
} else {
|
|
|
|
switch ( tblType ) {
|
|
case SCEJET_TABLE_SCP:
|
|
cxtProfile->JetScpID = TableCreate.tableid;
|
|
cxtProfile->JetScpSectionID = ColumnCreate[0].columnid;
|
|
cxtProfile->JetScpNameID = ColumnCreate[1].columnid;
|
|
cxtProfile->JetScpValueID = ColumnCreate[2].columnid;
|
|
cxtProfile->JetScpGpoID = ColumnCreate[3].columnid;
|
|
break;
|
|
case SCEJET_TABLE_SMP:
|
|
cxtProfile->JetSmpID = TableCreate.tableid;
|
|
cxtProfile->JetSmpSectionID = ColumnCreate[0].columnid;
|
|
cxtProfile->JetSmpNameID = ColumnCreate[1].columnid;
|
|
cxtProfile->JetSmpValueID = ColumnCreate[2].columnid;
|
|
break;
|
|
case SCEJET_TABLE_SAP:
|
|
case SCEJET_TABLE_TATTOO: // use the SAP handle
|
|
cxtProfile->JetSapID = TableCreate.tableid;
|
|
cxtProfile->JetSapSectionID = ColumnCreate[0].columnid;
|
|
cxtProfile->JetSapNameID = ColumnCreate[1].columnid;
|
|
cxtProfile->JetSapValueID = ColumnCreate[2].columnid;
|
|
break;
|
|
case SCEJET_TABLE_SECTION:
|
|
cxtProfile->JetTblSecID = TableCreate.tableid;
|
|
cxtProfile->JetSecNameID = ColumnCreate[1].columnid;
|
|
cxtProfile->JetSecID = ColumnCreate[0].columnid;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( tblType != SCEJET_TABLE_VERSION ) {
|
|
|
|
//
|
|
// Set current index in this table
|
|
//
|
|
JetErr = JetSetCurrentIndex(
|
|
cxtProfile->JetSessionID,
|
|
TableCreate.tableid,
|
|
"SectionKey"
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetOpenTable(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN LPSTR tblName,
|
|
IN SCEJET_TABLE_TYPE tblType,
|
|
IN SCEJET_OPEN_TYPE OpenType,
|
|
OUT JET_TABLEID *TableID
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine opens a table, gets column IDs for the column "Name" and
|
|
"Value" and saves them in the context.
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - The context handle
|
|
|
|
tblName - ASCII name of a table to open
|
|
|
|
tblType - The type of the table. It may be one of the following
|
|
SCEJET_TABLE_SCP
|
|
SCEJET_TABLE_SAP
|
|
SCEJET_TABLE_SMP
|
|
SCEJET_TABLE_VERSION
|
|
SCEJET_TABLE_SECTION
|
|
SCEJET_TABLE_GPO
|
|
SCEJET_TABLE_TATTOO
|
|
Return value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_ACCESS_DENIED
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
SCESTATUS_OTHER_ERROR
|
|
|
|
-- */
|
|
{
|
|
JET_ERR JetErr;
|
|
JET_TABLEID *tblID;
|
|
JET_TABLEID tmpTblID;
|
|
JET_COLUMNDEF ColumnDef;
|
|
JET_COLUMNID NameID=0;
|
|
JET_COLUMNID ValueID=0;
|
|
JET_COLUMNID SectionID=0;
|
|
JET_COLUMNID GpoColID=0;
|
|
SCESTATUS rc;
|
|
JET_GRBIT grbit=0;
|
|
|
|
if ( cxtProfile == NULL || tblName == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
// get address of table id
|
|
|
|
if ( TableID ) {
|
|
tblID = TableID;
|
|
|
|
} else {
|
|
|
|
switch (tblType) {
|
|
case SCEJET_TABLE_SCP:
|
|
tblID = &(cxtProfile->JetScpID);
|
|
break;
|
|
case SCEJET_TABLE_SAP:
|
|
case SCEJET_TABLE_TATTOO:
|
|
tblID = &(cxtProfile->JetSapID);
|
|
break;
|
|
case SCEJET_TABLE_SMP:
|
|
tblID = &(cxtProfile->JetSmpID);
|
|
break;
|
|
case SCEJET_TABLE_SECTION:
|
|
tblID = &(cxtProfile->JetTblSecID);
|
|
break;
|
|
|
|
default:
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
}
|
|
|
|
if ( OpenType == SCEJET_OPEN_READ_ONLY ) {
|
|
grbit = JET_bitTableReadOnly;
|
|
}
|
|
|
|
// open this table
|
|
JetErr = JetOpenTable(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetDbID,
|
|
tblName,
|
|
NULL,
|
|
0,
|
|
grbit,
|
|
&tmpTblID
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS )
|
|
*tblID = tmpTblID;
|
|
|
|
if ( TableID ) {
|
|
return(rc);
|
|
}
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
//
|
|
// SCP and SMP table must exist. SAP and Tattoo tables are optional.
|
|
//
|
|
if ( tblType != SCEJET_TABLE_SCP &&
|
|
tblType != SCEJET_TABLE_SMP &&
|
|
tblType != SCEJET_TABLE_SECTION &&
|
|
( rc == SCESTATUS_BAD_FORMAT ||
|
|
rc == SCESTATUS_PROFILE_NOT_FOUND) ) {
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
return(rc);
|
|
}
|
|
|
|
//
|
|
// get column id for Column "SectionID"
|
|
//
|
|
JetErr = JetGetTableColumnInfo(
|
|
cxtProfile->JetSessionID,
|
|
*tblID,
|
|
"SectionID",
|
|
(VOID *)&ColumnDef,
|
|
sizeof(JET_COLUMNDEF),
|
|
0
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
return(rc);
|
|
}
|
|
SectionID = ColumnDef.columnid;
|
|
|
|
//
|
|
// get column id for Column "Name"
|
|
//
|
|
JetErr = JetGetTableColumnInfo(
|
|
cxtProfile->JetSessionID,
|
|
*tblID,
|
|
"Name",
|
|
(VOID *)&ColumnDef,
|
|
sizeof(JET_COLUMNDEF),
|
|
0
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
return(rc);
|
|
}
|
|
NameID = ColumnDef.columnid;
|
|
|
|
if ( tblType == SCEJET_TABLE_SCP ||
|
|
tblType == SCEJET_TABLE_SAP ||
|
|
tblType == SCEJET_TABLE_SMP ||
|
|
tblType == SCEJET_TABLE_TATTOO ) {
|
|
|
|
//
|
|
// get column id for Column "Value"
|
|
//
|
|
JetErr = JetGetTableColumnInfo(
|
|
cxtProfile->JetSessionID,
|
|
*tblID,
|
|
"Value",
|
|
(VOID *)&ColumnDef,
|
|
sizeof(JET_COLUMNDEF),
|
|
0
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
return(rc);
|
|
}
|
|
ValueID = ColumnDef.columnid;
|
|
|
|
if ( tblType == SCEJET_TABLE_SCP ) {
|
|
//
|
|
// get column id for column GpoID
|
|
//
|
|
JetErr = JetGetTableColumnInfo(
|
|
cxtProfile->JetSessionID,
|
|
*tblID,
|
|
"GpoID",
|
|
(VOID *)&ColumnDef,
|
|
sizeof(JET_COLUMNDEF),
|
|
0
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
return(rc);
|
|
}
|
|
GpoColID = ColumnDef.columnid;
|
|
}
|
|
}
|
|
|
|
//
|
|
// save the column ids
|
|
//
|
|
switch (tblType) {
|
|
case SCEJET_TABLE_SCP:
|
|
cxtProfile->JetScpSectionID = SectionID;
|
|
cxtProfile->JetScpNameID = NameID;
|
|
cxtProfile->JetScpValueID = ValueID;
|
|
cxtProfile->JetScpGpoID = GpoColID;
|
|
break;
|
|
case SCEJET_TABLE_SAP:
|
|
case SCEJET_TABLE_TATTOO:
|
|
cxtProfile->JetSapSectionID = SectionID;
|
|
cxtProfile->JetSapNameID = NameID;
|
|
cxtProfile->JetSapValueID = ValueID;
|
|
break;
|
|
case SCEJET_TABLE_SMP:
|
|
cxtProfile->JetSmpSectionID = SectionID;
|
|
cxtProfile->JetSmpNameID = NameID;
|
|
cxtProfile->JetSmpValueID = ValueID;
|
|
break;
|
|
case SCEJET_TABLE_SECTION:
|
|
cxtProfile->JetSecID = SectionID;
|
|
cxtProfile->JetSecNameID = NameID;
|
|
}
|
|
|
|
//
|
|
// Set current index
|
|
//
|
|
|
|
JetErr = JetSetCurrentIndex(
|
|
cxtProfile->JetSessionID,
|
|
*tblID,
|
|
"SectionKey"
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetDeleteTable(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN LPSTR tblName,
|
|
IN SCEJET_TABLE_TYPE tblType
|
|
)
|
|
{
|
|
JET_ERR JetErr;
|
|
JET_TABLEID *tblID;
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
|
|
|
|
if ( cxtProfile == NULL || tblName == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
// get address of table id
|
|
switch (tblType) {
|
|
case SCEJET_TABLE_SCP:
|
|
tblID = &(cxtProfile->JetScpID);
|
|
break;
|
|
case SCEJET_TABLE_SAP:
|
|
case SCEJET_TABLE_TATTOO:
|
|
tblID = &(cxtProfile->JetSapID);
|
|
break;
|
|
case SCEJET_TABLE_SMP:
|
|
tblID = &(cxtProfile->JetSmpID);
|
|
break;
|
|
case SCEJET_TABLE_SECTION:
|
|
tblID = &(cxtProfile->JetTblSecID);
|
|
break;
|
|
default:
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
// close this table
|
|
if ( *tblID != JET_tableidNil ) {
|
|
JetErr = JetCloseTable(
|
|
cxtProfile->JetSessionID,
|
|
*tblID
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
*tblID = JET_tableidNil;
|
|
|
|
//
|
|
// reset each column id
|
|
//
|
|
switch (tblType) {
|
|
case SCEJET_TABLE_SCP:
|
|
cxtProfile->JetScpSectionID = 0;
|
|
cxtProfile->JetScpNameID = 0;
|
|
cxtProfile->JetScpValueID = 0;
|
|
cxtProfile->JetScpGpoID = 0;
|
|
break;
|
|
case SCEJET_TABLE_SAP:
|
|
case SCEJET_TABLE_TATTOO:
|
|
cxtProfile->JetSapSectionID = 0;
|
|
cxtProfile->JetSapNameID = 0;
|
|
cxtProfile->JetSapValueID = 0;
|
|
break;
|
|
case SCEJET_TABLE_SMP:
|
|
cxtProfile->JetSmpSectionID = 0;
|
|
cxtProfile->JetSmpNameID = 0;
|
|
cxtProfile->JetSmpValueID = 0;
|
|
break;
|
|
case SCEJET_TABLE_SECTION:
|
|
cxtProfile->JetSecNameID = 0;
|
|
cxtProfile->JetSecID = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
JetErr = JetDeleteTable(cxtProfile->JetSessionID,
|
|
cxtProfile->JetDbID,
|
|
tblName
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_BAD_FORMAT )
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetCheckVersion(
|
|
IN PSCECONTEXT cxtProfile,
|
|
OUT FLOAT *pVersion OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine checks the version table in the database to see if the
|
|
database is for the security manager, also if the version # is the
|
|
correct one.
|
|
|
|
The version table is named "SmTblVersion" and has a Version column
|
|
in it. The current version # is 1.2
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - The profile context
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_OTHER_ERROR
|
|
SCESTATUS from SceJetOpenTable
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
FLOAT Version=(FLOAT)1.0;
|
|
DWORD Actual;
|
|
|
|
|
|
if ( cxtProfile == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
rc = SceJetpGetValueFromVersion(
|
|
cxtProfile,
|
|
"SmTblVersion",
|
|
"Version",
|
|
(LPSTR)&Version,
|
|
4, // number of bytes
|
|
&Actual
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ||
|
|
rc == SCESTATUS_BUFFER_TOO_SMALL ) {
|
|
|
|
if ( Version != (FLOAT)1.2 )
|
|
rc = SCESTATUS_BAD_FORMAT;
|
|
else
|
|
rc = SCESTATUS_SUCCESS;
|
|
}
|
|
|
|
if ( pVersion ) {
|
|
*pVersion = Version;
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetGetSectionIDByName(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN PCWSTR Name,
|
|
OUT DOUBLE *SectionID OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine retrieve the section ID for the name in the Section table.
|
|
If SectionID is NULL, this routine really does a seek by name. The cursor
|
|
will be on the record if there is a successful match.
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - The profile context handle
|
|
|
|
Name - The section name looked for
|
|
|
|
SectionID - The output section ID if there is a successful match
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_RECORD_NOT_FOUND
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_OTHER_ERROR
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
JET_ERR JetErr;
|
|
DWORD Actual;
|
|
PWSTR LwrName=NULL;
|
|
DWORD Len;
|
|
|
|
if ( cxtProfile == NULL || Name == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
if ( cxtProfile->JetTblSecID <= 0) {
|
|
//
|
|
// Section table is not opened yet
|
|
//
|
|
rc = SceJetOpenTable(
|
|
cxtProfile,
|
|
"SmTblSection",
|
|
SCEJET_TABLE_SECTION,
|
|
SCEJET_OPEN_READ_ONLY,
|
|
NULL
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
}
|
|
|
|
//
|
|
// set current index to SectionKey (the name)
|
|
//
|
|
JetErr = JetSetCurrentIndex(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
"SectionKey"
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
Len = wcslen(Name);
|
|
LwrName = (PWSTR)ScepAlloc(0, (Len+1)*sizeof(WCHAR));
|
|
|
|
if ( LwrName != NULL ) {
|
|
|
|
wcscpy(LwrName, Name);
|
|
LwrName = _wcslwr(LwrName);
|
|
|
|
JetErr = JetMakeKey(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
(VOID *)LwrName,
|
|
Len*sizeof(WCHAR),
|
|
JET_bitNewKey
|
|
);
|
|
|
|
if ( JetErr == JET_errKeyIsMade ) {
|
|
//
|
|
// Only one key is needed, it may return this code, even on success.
|
|
//
|
|
JetErr = JET_errSuccess;
|
|
}
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
JetErr = JetSeek(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
JET_bitSeekEQ
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// find the section name, retrieve column SectionID
|
|
//
|
|
if ( SectionID != NULL) {
|
|
JetErr = JetRetrieveColumn(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
cxtProfile->JetSecID,
|
|
(void *)SectionID,
|
|
8,
|
|
&Actual,
|
|
0,
|
|
NULL
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
ScepFree(LwrName);
|
|
|
|
} else
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetGetSectionNameByID(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN DOUBLE SectionID,
|
|
OUT PWSTR Name OPTIONAL,
|
|
IN OUT LPDWORD pNameLen OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine retrieve the section name for the ID in the Section table.
|
|
If Name is NULL, this routine really does a seek by ID. The cursor will
|
|
be on the record if there is a successful match.
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - The profile context handle
|
|
|
|
SectionID - The section ID looking for
|
|
|
|
Name - The optional output buffer for section name
|
|
|
|
pNameLen - The name buffer's length
|
|
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_RECORD_NOT_FOUND
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_OTHER_ERROR
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
JET_ERR JetErr;
|
|
DWORD Actual;
|
|
|
|
|
|
if ( cxtProfile == NULL || (Name != NULL && pNameLen == NULL) )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
if ( cxtProfile->JetTblSecID <= 0) {
|
|
//
|
|
// Section table is not opened yet
|
|
//
|
|
rc = SceJetOpenTable(
|
|
cxtProfile,
|
|
"SmTblSection",
|
|
SCEJET_TABLE_SECTION,
|
|
SCEJET_OPEN_READ_ONLY,
|
|
NULL
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
}
|
|
|
|
//
|
|
// set current index to SecID (the ID)
|
|
//
|
|
JetErr = JetSetCurrentIndex(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
"SecID"
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
JetErr = JetMakeKey(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
(VOID *)(&SectionID),
|
|
8,
|
|
JET_bitNewKey
|
|
);
|
|
|
|
if ( JetErr == JET_errKeyIsMade ) {
|
|
//
|
|
// Only one key is needed, it may return this code, even on success.
|
|
//
|
|
JetErr = JET_errSuccess;
|
|
}
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
JetErr = JetSeek(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
JET_bitSeekEQ
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// find the section ID, retrieve column Name
|
|
//
|
|
if ( Name != NULL ) {
|
|
JetErr = JetRetrieveColumn(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
cxtProfile->JetSecNameID,
|
|
(void *)Name,
|
|
*pNameLen,
|
|
&Actual,
|
|
0,
|
|
NULL
|
|
);
|
|
*pNameLen = Actual;
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetAddSection(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN PCWSTR Name,
|
|
OUT DOUBLE *SectionID
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
DWORD Len;
|
|
JET_ERR JetErr;
|
|
PWSTR LwrName=NULL;
|
|
|
|
|
|
if ( cxtProfile == NULL ||
|
|
Name == NULL ||
|
|
SectionID == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
rc = SceJetGetSectionIDByName(
|
|
cxtProfile,
|
|
Name,
|
|
SectionID
|
|
);
|
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
//
|
|
// the record is not there. add it in
|
|
// get the next available section ID first.
|
|
//
|
|
Len = wcslen(Name)*sizeof(WCHAR);
|
|
LwrName = (PWSTR)ScepAlloc(0, Len+2);
|
|
|
|
if ( LwrName != NULL ) {
|
|
|
|
rc = SceJetpGetAvailableSectionID(
|
|
cxtProfile,
|
|
SectionID
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// add a record to the section table
|
|
//
|
|
JetErr = JetPrepareUpdate(cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
JET_prepInsert
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// set SectionID and name
|
|
//
|
|
|
|
JetErr = JetSetColumn(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
cxtProfile->JetSecID,
|
|
(void *)SectionID,
|
|
8,
|
|
0, //JET_bitSetOverwriteLV,
|
|
NULL
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// set Name column
|
|
//
|
|
wcscpy(LwrName, Name);
|
|
LwrName = _wcslwr(LwrName);
|
|
|
|
JetErr = JetSetColumn(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
cxtProfile->JetSecNameID,
|
|
(void *)LwrName,
|
|
Len,
|
|
0,
|
|
NULL
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
}
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
//
|
|
// if setting fails, cancel the prepared record
|
|
//
|
|
JetPrepareUpdate( cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
JET_prepCancel
|
|
);
|
|
} else {
|
|
|
|
//
|
|
// Setting columns succeed. Update the record
|
|
//
|
|
JetErr = JetUpdate(cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
NULL,
|
|
0,
|
|
&Len
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
}
|
|
}
|
|
ScepFree(LwrName);
|
|
}
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetDeleteSectionID(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN DOUBLE SectionID,
|
|
IN PCWSTR Name
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine deletes a record from the SmTblSection table. If SectionID
|
|
is not 0, the record will be deleted by ID if there is a match on ID.
|
|
Otherwise, the record will be deleted by Name if there is a match on Name.
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - The profile context handle
|
|
|
|
SectionID - The SectionID to delete (if it is not 0)
|
|
|
|
Name - The section name to delete (if it is not NULL ).
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_ACCESS_DENIED
|
|
SCESTATUS_OTHER_ERROR
|
|
|
|
SCESTATUS from SceJetGetSectionIDByName
|
|
SCESTATUS from SceJetGetSectionNameByID
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
JET_ERR JetErr;
|
|
|
|
|
|
if ( cxtProfile == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
|
|
if ( SectionID > (DOUBLE)0 ) {
|
|
//
|
|
// delete by SectionID
|
|
//
|
|
rc = SceJetGetSectionNameByID(
|
|
cxtProfile,
|
|
SectionID,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
// find it
|
|
JetErr = JetDelete(cxtProfile->JetSessionID, cxtProfile->JetTblSecID);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
}
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
if ( Name != NULL && wcslen(Name) > 0 ) {
|
|
//
|
|
// delete by Name
|
|
//
|
|
rc = SceJetGetSectionIDByName(
|
|
cxtProfile,
|
|
Name,
|
|
NULL
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
// find it
|
|
JetErr = JetDelete(cxtProfile->JetSessionID, cxtProfile->JetTblSecID);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Other private APIs
|
|
//
|
|
JET_ERR
|
|
SceJetpSeek(
|
|
IN PSCESECTION hSection,
|
|
IN PWSTR LinePrefix,
|
|
IN DWORD PrefixLength,
|
|
IN SCEJET_SEEK_FLAG SeekBit,
|
|
IN BOOL bOkNoMatch
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine seeks to the current key as built with SceJetpMakeKey.
|
|
If there is no records start with the SectionID+LinePrefix, a
|
|
JET_errRecordNotFound is returned. This is similar to exact or partial
|
|
match search.
|
|
|
|
There is a 255 bytes limit on Jet engine's index. If SectionID plus
|
|
the line prefix is over this limit, this routine will scroll to the next
|
|
record until find a line starting with SectionID + LinePrefix.
|
|
|
|
Arguments:
|
|
|
|
hSection - the context handle of the section
|
|
|
|
LinePrefix - The prefix for fields to start with
|
|
|
|
PrefixLength- The length of the prefix in BYTES
|
|
|
|
grbit - The option for JetSeek
|
|
|
|
Return Value:
|
|
|
|
JET_ERR returned from JetMakeKey,JetSeek,JetRetrieveColumn, JetMove
|
|
|
|
-- */
|
|
{
|
|
JET_ERR JetErr;
|
|
INT Result=0;
|
|
JET_GRBIT grbit;
|
|
DWORD Actual;
|
|
|
|
//
|
|
// make the key first
|
|
//
|
|
JetErr = SceJetpMakeKey(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
hSection->SectionID,
|
|
LinePrefix,
|
|
PrefixLength
|
|
);
|
|
if ( JetErr != JET_errSuccess ) {
|
|
return(JetErr);
|
|
}
|
|
//
|
|
// Call Jet engine's JetSeek to take to the first line
|
|
// to start with.
|
|
//
|
|
switch ( SeekBit ) {
|
|
case SCEJET_SEEK_EQ:
|
|
grbit = JET_bitSeekEQ;
|
|
break;
|
|
case SCEJET_SEEK_GT:
|
|
if ( LinePrefix != NULL && PrefixLength > 247 )
|
|
grbit = JET_bitSeekGE;
|
|
else
|
|
grbit = JET_bitSeekGT;
|
|
break;
|
|
default:
|
|
grbit = JET_bitSeekGE;
|
|
}
|
|
JetErr = JetSeek(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
grbit
|
|
);
|
|
|
|
if ( JetErr == JET_errSuccess ||
|
|
JetErr == JET_wrnSeekNotEqual ) {
|
|
|
|
if ( LinePrefix != NULL && PrefixLength > 247 ) {
|
|
//
|
|
// info is truncated
|
|
// The current record may be before the actual one
|
|
//
|
|
do {
|
|
//
|
|
// check the current record
|
|
//
|
|
JetErr = SceJetpCompareLine(
|
|
hSection,
|
|
grbit,
|
|
LinePrefix,
|
|
PrefixLength,
|
|
&Result,
|
|
&Actual
|
|
);
|
|
if ( JetErr == JET_errSuccess &&
|
|
( Result < 0 || (Result == 0 && SeekBit == SCEJET_SEEK_GT) )) {
|
|
//
|
|
// current record's data is less than the prefix, move to next
|
|
//
|
|
JetErr = JetMove(hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
JET_MoveNext,
|
|
0
|
|
);
|
|
if ( JetErr == JET_errNoCurrentRecord )
|
|
JetErr = JET_errRecordNotFound;
|
|
}
|
|
} while ( JetErr == JET_errSuccess &&
|
|
( (Result < 0 && SeekBit != SCEJET_SEEK_EQ) ||
|
|
(Result == 0 && SeekBit == SCEJET_SEEK_GT) ) );
|
|
|
|
if ( SeekBit == SCEJET_SEEK_EQ && JetErr == JET_errSuccess &&
|
|
Result == 0 && Actual > PrefixLength ) {
|
|
//
|
|
// no exact match
|
|
//
|
|
return(JET_errRecordNotFound);
|
|
|
|
} // for SEEK_GE check, see below
|
|
|
|
} else {
|
|
//
|
|
// Prefix is not overlimit. Check the current record only.
|
|
//
|
|
if (SeekBit != SCEJET_SEEK_EQ)
|
|
JetErr = SceJetpCompareLine(
|
|
hSection,
|
|
grbit,
|
|
LinePrefix,
|
|
PrefixLength,
|
|
&Result,
|
|
0
|
|
);
|
|
}
|
|
|
|
if ( JetErr == JET_errSuccess && Result > 0 ) {
|
|
if ( SeekBit == SCEJET_SEEK_EQ ) {
|
|
//
|
|
// Prefix is less than the current line, which is OK if for SEEK_GE and SEEK_GT
|
|
//
|
|
return(JET_errRecordNotFound);
|
|
|
|
} else if ( SeekBit == SCEJET_SEEK_GE && LinePrefix && PrefixLength && !bOkNoMatch ) {
|
|
//
|
|
return(JET_errRecordNotFound);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return(JetErr);
|
|
}
|
|
|
|
|
|
JET_ERR
|
|
SceJetpCompareLine(
|
|
IN PSCESECTION hSection,
|
|
IN JET_GRBIT grbit,
|
|
IN PWSTR LinePrefix OPTIONAL,
|
|
IN DWORD PrefixLength,
|
|
OUT INT *Result,
|
|
OUT DWORD *ActualLength OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine comapre the current line with the SectionID in the section
|
|
handle and name column with LinePrefix if LinePrefix is not NULL. The
|
|
purpose of this routine is to see if the cursor is still on a record
|
|
which has the same sectionID and prefix.
|
|
|
|
The comparsion result is output from Result. If JET_errSuccess returns
|
|
and Result < 0, the current record is BEFORE the prefix; If Result = 0,
|
|
the current record has the same key with prefix; If Result > 0, the
|
|
current record is AFTER the prefix. If no more record is available to
|
|
be compared, JET_errRecordNotFound returns. Any other error occurs inside
|
|
the routine is returned.
|
|
|
|
Arguments:
|
|
|
|
hSection - the section handle
|
|
|
|
LinePrefix - The prefix to match
|
|
|
|
PrefixLength - The number of BYTES in LinePrefix
|
|
|
|
Return Value:
|
|
|
|
JET_errSuccess
|
|
JET_errRecordNotFound
|
|
JET_errOutOfMemory
|
|
JET_ERR returned from JetRetrieveColumn
|
|
|
|
-- */
|
|
{
|
|
JET_ERR JetErr;
|
|
DOUBLE SectionID;
|
|
DWORD Actual;
|
|
JET_RETINFO RetInfo;
|
|
PWSTR Buffer=NULL;
|
|
|
|
// *Result = 0;
|
|
// return(JET_errSuccess);
|
|
//
|
|
// Compare the section first
|
|
//
|
|
JetErr = JetRetrieveColumn(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
hSection->JetColumnSectionID,
|
|
(void *)&SectionID,
|
|
8,
|
|
&Actual,
|
|
0,
|
|
NULL
|
|
);
|
|
if ( JetErr == JET_errNoCurrentRecord )
|
|
return(JET_errRecordNotFound);
|
|
|
|
else if ( JetErr != JET_errSuccess )
|
|
return(JetErr);
|
|
|
|
if ( hSection->SectionID < SectionID ) {
|
|
*Result = 1;
|
|
// if ( grbit != JET_bitSeekGT )
|
|
return(JET_errRecordNotFound);
|
|
|
|
} else if ( hSection->SectionID == SectionID )
|
|
*Result = 0;
|
|
else
|
|
*Result = -1;
|
|
|
|
if ( *Result != 0 || grbit == JET_bitSeekGT )
|
|
return(JetErr);
|
|
|
|
//
|
|
// check Name column
|
|
//
|
|
if ( LinePrefix != NULL && PrefixLength > 0 ) {
|
|
RetInfo.ibLongValue = 0;
|
|
RetInfo.cbStruct = sizeof(JET_RETINFO);
|
|
RetInfo.itagSequence = 1;
|
|
|
|
Buffer = (PWSTR)LocalAlloc(LMEM_ZEROINIT, PrefixLength+2);
|
|
if ( Buffer == NULL )
|
|
return(JET_errOutOfMemory);
|
|
|
|
JetErr = JetRetrieveColumn(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
hSection->JetColumnNameID,
|
|
(void *)Buffer,
|
|
PrefixLength,
|
|
&Actual,
|
|
0,
|
|
&RetInfo
|
|
);
|
|
|
|
if ( JetErr == JET_errNoCurrentRecord )
|
|
JetErr = JET_errRecordNotFound;
|
|
|
|
if ( JetErr != JET_errSuccess &&
|
|
JetErr != JET_wrnBufferTruncated ) {
|
|
|
|
if ( JetErr > 0 ) {
|
|
// warnings, do not return equal
|
|
JetErr = JET_errSuccess;
|
|
*Result = 1;
|
|
}
|
|
LocalFree(Buffer);
|
|
return(JetErr);
|
|
}
|
|
|
|
JetErr = JET_errSuccess;
|
|
|
|
//
|
|
// Compare the first PrefixLength bytes.
|
|
//
|
|
*Result = _wcsnicmp(Buffer,
|
|
LinePrefix,
|
|
PrefixLength/sizeof(WCHAR));
|
|
//printf("Compare %ws to %ws for Length %d: Result=%d\n", Buffer, LinePrefix, PrefixLength/2, *Result);
|
|
LocalFree(Buffer);
|
|
|
|
if ( ActualLength != NULL )
|
|
*ActualLength = Actual;
|
|
}
|
|
|
|
return(JetErr);
|
|
}
|
|
|
|
|
|
JET_ERR
|
|
SceJetpMakeKey(
|
|
IN JET_SESID SessionID,
|
|
IN JET_TABLEID TableID,
|
|
IN DOUBLE SectionID,
|
|
IN PWSTR LinePrefix,
|
|
IN DWORD PrefixLength
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine constructs a normalized key value for Seek. It constructs
|
|
the section name in the section context first. Then the LinePrefix is
|
|
added if it is not NULL.
|
|
|
|
The scp, sap and smp tables all have one index which is Section+Name.
|
|
|
|
Arguments:
|
|
|
|
SessionID - the Jet session ID
|
|
|
|
TableID - The Jet table ID to work in
|
|
|
|
SectionID - The ID in column "SectionID"
|
|
|
|
LinePrefix - The prefix for fields to start with
|
|
|
|
PrefixLength- The length of the prefix in BYTES
|
|
|
|
Return Value:
|
|
|
|
JET_ERR from JetMakeKey
|
|
-- */
|
|
{
|
|
JET_ERR JetErr;
|
|
JET_GRBIT grbit;
|
|
|
|
|
|
if ( LinePrefix == NULL ) {
|
|
grbit = JET_bitNewKey; // | JET_bitStrLimit; having StrLimit set takes you to the next key
|
|
} else {
|
|
grbit = JET_bitNewKey;
|
|
}
|
|
|
|
//
|
|
// Add section ID to the key
|
|
//
|
|
JetErr = JetMakeKey(
|
|
SessionID,
|
|
TableID,
|
|
(VOID *)(&SectionID),
|
|
8,
|
|
grbit
|
|
);
|
|
|
|
if ( JetErr != JET_errSuccess )
|
|
return(JetErr);
|
|
|
|
//
|
|
// add prefix to the key if it is not NULL
|
|
//
|
|
if ( LinePrefix != NULL ) {
|
|
JetErr = JetMakeKey(
|
|
SessionID,
|
|
TableID,
|
|
(VOID *)LinePrefix,
|
|
PrefixLength,
|
|
JET_bitSubStrLimit
|
|
);
|
|
}
|
|
|
|
if ( JetErr == JET_errKeyIsMade ) {
|
|
//
|
|
// When 2 keys are provided, it may return this code, even on success.
|
|
//
|
|
JetErr = JET_errSuccess;
|
|
}
|
|
|
|
return(JetErr);
|
|
|
|
}
|
|
|
|
|
|
JET_ERR
|
|
SceJetpBuildUpperLimit(
|
|
IN PSCESECTION hSection,
|
|
IN PWSTR LinePrefix,
|
|
IN DWORD Len,
|
|
IN BOOL bReserveCase
|
|
)
|
|
/* ++
|
|
Function Descripton:
|
|
|
|
This routine builts an upper index range based on a section and an
|
|
optional prefix. If prefix is NULL, the upper limit is the next
|
|
available sectionID. If prefix is not NULL, the upper limit is the
|
|
last character 's next character in the key.
|
|
|
|
For example, if prefix is a\b\c\d\e\f\g, the upper limit is then
|
|
a\b\c\d\e\f\h. If prefix is over 247 (index limit), e.g.,
|
|
|
|
aaa...\b..\c...\d...\e...\f\x\t\y\z
|
|
|
|
^
|
|
|
|
|
the 247th byte.
|
|
then the upper limit is built to aaa...\b..\c...\d...\e...\g
|
|
|
|
Arguments:
|
|
|
|
hSection - The seciton's handle
|
|
|
|
LinePrefix - The prefix
|
|
|
|
Len - The number of bytes in the prefix
|
|
|
|
Return Value:
|
|
|
|
JET_ERR from SceJetpMakeKey, JetSetIndexRange
|
|
|
|
-- */
|
|
{
|
|
JET_ERR JetErr;
|
|
DWORD indx;
|
|
WCHAR UpperLimit[128];
|
|
|
|
|
|
if ( Len == 0 ) {
|
|
// no prefix. The upper limit is the next available section ID
|
|
JetErr = SceJetpMakeKey(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
hSection->SectionID+(DOUBLE)1,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
} else {
|
|
|
|
memset(UpperLimit, 0, 128*sizeof(WCHAR));
|
|
|
|
if ( Len < 247 )
|
|
// prefix is not overlimit.
|
|
// The upper limit is the last character + 1
|
|
indx = Len / sizeof(WCHAR);
|
|
else
|
|
// prefix is overlimit (247)
|
|
// built range on 247 bytes
|
|
indx = 123;
|
|
|
|
wcsncpy(UpperLimit, LinePrefix, indx);
|
|
UpperLimit[indx] = L'\0';
|
|
|
|
if ( !bReserveCase ) {
|
|
_wcslwr(UpperLimit);
|
|
}
|
|
UpperLimit[indx-1] = (WCHAR) (UpperLimit[indx-1] + 1);
|
|
|
|
JetErr = SceJetpMakeKey(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
hSection->SectionID,
|
|
UpperLimit,
|
|
Len
|
|
);
|
|
}
|
|
|
|
if ( JetErr != JET_errSuccess )
|
|
return(JetErr);
|
|
|
|
//
|
|
// set upper limit
|
|
//
|
|
JetErr = JetSetIndexRange(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
JET_bitRangeUpperLimit //| JET_bitRangeInclusive
|
|
);
|
|
|
|
return(JetErr);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetJetErrorToSceStatus(
|
|
IN JET_ERR JetErr
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine converts error returned from Jet engine (JET_ERR) to SCESTATUS.
|
|
|
|
Arguments:
|
|
|
|
JetErr - The error returned from Jet engine
|
|
|
|
Return Value:
|
|
|
|
All available SCESTATUS error codes
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
|
|
switch ( JetErr ) {
|
|
case JET_errSuccess:
|
|
case JET_wrnSeekNotEqual:
|
|
case JET_wrnNoErrorInfo:
|
|
case JET_wrnColumnNull:
|
|
case JET_wrnColumnSetNull:
|
|
case JET_wrnTableEmpty:
|
|
case JET_errAlreadyInitialized:
|
|
|
|
rc = SCESTATUS_SUCCESS;
|
|
break;
|
|
|
|
case JET_errDatabaseInvalidName:
|
|
|
|
rc = SCESTATUS_INVALID_PARAMETER;
|
|
break;
|
|
|
|
case JET_errNoCurrentRecord:
|
|
case JET_errRecordNotFound:
|
|
|
|
rc = SCESTATUS_RECORD_NOT_FOUND;
|
|
break;
|
|
|
|
case JET_errColumnDoesNotFit:
|
|
case JET_errColumnTooBig:
|
|
|
|
rc = SCESTATUS_INVALID_DATA;
|
|
break;
|
|
|
|
case JET_errDatabaseDuplicate:
|
|
case JET_errTableDuplicate:
|
|
case JET_errColumnDuplicate:
|
|
case JET_errIndexDuplicate:
|
|
case JET_errKeyDuplicate:
|
|
|
|
rc = SCESTATUS_OBJECT_EXIST;
|
|
break;
|
|
|
|
case JET_wrnBufferTruncated:
|
|
|
|
rc = SCESTATUS_BUFFER_TOO_SMALL;
|
|
break;
|
|
|
|
case JET_errFileNotFound:
|
|
case JET_errDatabaseNotFound:
|
|
|
|
rc = SCESTATUS_PROFILE_NOT_FOUND;
|
|
break;
|
|
|
|
case JET_errObjectNotFound:
|
|
case JET_errIndexNotFound:
|
|
case JET_errColumnNotFound:
|
|
case JET_errDatabaseCorrupted:
|
|
|
|
rc = SCESTATUS_BAD_FORMAT;
|
|
break;
|
|
|
|
case JET_errTooManyOpenDatabases:
|
|
case JET_errTooManyOpenTables:
|
|
case JET_errDiskFull:
|
|
case JET_errOutOfMemory:
|
|
case JET_errVersionStoreOutOfMemory:
|
|
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
break;
|
|
|
|
case JET_errPermissionDenied:
|
|
case JET_errFileAccessDenied:
|
|
case JET_errTableInUse:
|
|
case JET_errTableLocked:
|
|
case JET_errWriteConflict:
|
|
|
|
rc = SCESTATUS_ACCESS_DENIED;
|
|
break;
|
|
|
|
case JET_errFeatureNotAvailable:
|
|
case JET_errQueryNotSupported:
|
|
case JET_errSQLLinkNotSupported:
|
|
case JET_errLinkNotSupported:
|
|
case JET_errIllegalOperation:
|
|
|
|
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
|
break;
|
|
|
|
default:
|
|
//printf("JetErr=%d\n", JetErr);
|
|
rc = SCESTATUS_OTHER_ERROR;
|
|
break;
|
|
}
|
|
return(rc);
|
|
}
|
|
|
|
|
|
|
|
SCESTATUS
|
|
SceJetpGetAvailableSectionID(
|
|
IN PSCECONTEXT cxtProfile,
|
|
OUT DOUBLE *SectionID
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - The profile context handle
|
|
|
|
SectionID - The output section ID
|
|
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_RECORD_NOT_FOUND
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_OTHER_ERROR
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
JET_ERR JetErr;
|
|
DWORD Actual;
|
|
|
|
|
|
if ( cxtProfile == NULL || SectionID == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
if ( cxtProfile->JetTblSecID <= 0) {
|
|
//
|
|
// Section table is not opened yet
|
|
//
|
|
rc = SceJetOpenTable(
|
|
cxtProfile,
|
|
"SmTblSection",
|
|
SCEJET_TABLE_SECTION,
|
|
SCEJET_OPEN_READ_ONLY,
|
|
NULL
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
}
|
|
|
|
*SectionID = (DOUBLE)0;
|
|
|
|
//
|
|
// set current index to SecID (the ID)
|
|
//
|
|
JetErr = JetSetCurrentIndex(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
"SecID"
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
//
|
|
// Move to the last record
|
|
//
|
|
JetErr = JetMove(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
JET_MoveLast,
|
|
0
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// find the section ID, retrieve column Name
|
|
//
|
|
JetErr = JetRetrieveColumn(
|
|
cxtProfile->JetSessionID,
|
|
cxtProfile->JetTblSecID,
|
|
cxtProfile->JetSecID,
|
|
(void *)SectionID,
|
|
8,
|
|
&Actual,
|
|
0,
|
|
NULL
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// The next available ID is current ID + 1
|
|
//
|
|
*SectionID = *SectionID + (DOUBLE)1;
|
|
}
|
|
} else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
|
|
*SectionID = (DOUBLE)1;
|
|
rc = SCESTATUS_SUCCESS;
|
|
}
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetpAddAllSections(
|
|
IN PSCECONTEXT cxtProfile
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine adds all pre-defined sections into the section table.
|
|
This routine is used when creating the section table.
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - The profile context
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS from SceJetAddSection
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
DOUBLE SectionID;
|
|
|
|
|
|
rc = SceJetAddSection(
|
|
cxtProfile,
|
|
szSystemAccess,
|
|
&SectionID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
rc = SceJetAddSection(
|
|
cxtProfile,
|
|
szPrivilegeRights,
|
|
&SectionID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
rc = SceJetAddSection(
|
|
cxtProfile,
|
|
szGroupMembership,
|
|
&SectionID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
rc = SceJetAddSection(
|
|
cxtProfile,
|
|
szAccountProfiles,
|
|
&SectionID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
rc = SceJetAddSection(
|
|
cxtProfile,
|
|
szRegistryKeys,
|
|
&SectionID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
rc = SceJetAddSection(
|
|
cxtProfile,
|
|
szFileSecurity,
|
|
&SectionID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
rc = SceJetAddSection(
|
|
cxtProfile,
|
|
szDSSecurity,
|
|
&SectionID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
rc = SceJetAddSection(
|
|
cxtProfile,
|
|
szAuditSystemLog,
|
|
&SectionID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
rc = SceJetAddSection(
|
|
cxtProfile,
|
|
szAuditSecurityLog,
|
|
&SectionID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
rc = SceJetAddSection(
|
|
cxtProfile,
|
|
szAuditApplicationLog,
|
|
&SectionID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
rc = SceJetAddSection(
|
|
cxtProfile,
|
|
szAuditEvent,
|
|
&SectionID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
rc = SceJetAddSection(
|
|
cxtProfile,
|
|
szUserList,
|
|
&SectionID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
rc = SceJetAddSection(
|
|
cxtProfile,
|
|
szKerberosPolicy,
|
|
&SectionID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
rc = SceJetAddSection(
|
|
cxtProfile,
|
|
szServiceGeneral,
|
|
&SectionID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
rc = SceJetAddSection(
|
|
cxtProfile,
|
|
szRegistryValues,
|
|
&SectionID
|
|
);
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetpConfigJetSystem(
|
|
IN JET_INSTANCE *hinstance
|
|
)
|
|
{
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
DWORD Win32rc;
|
|
JET_ERR JetErr;
|
|
|
|
DWORD Len;
|
|
PWSTR SysRoot=NULL;
|
|
|
|
PWSTR ProfileLocation=NULL;
|
|
CHAR FileName[512];
|
|
|
|
PSECURITY_DESCRIPTOR pSD=NULL;
|
|
SECURITY_INFORMATION SeInfo;
|
|
DWORD SDsize;
|
|
|
|
//
|
|
// the default Jet working directory is always in %SystemRoot%\security
|
|
// no matter who is logged on.
|
|
// this way allows one jet working directory
|
|
//
|
|
Len = 0;
|
|
Win32rc = ScepGetNTDirectory( &SysRoot, &Len, SCE_FLAG_WINDOWS_DIR );
|
|
|
|
if ( Win32rc == NO_ERROR ) {
|
|
|
|
if ( SysRoot != NULL ) {
|
|
Len += 9; // profile location
|
|
|
|
ProfileLocation = (PWSTR)ScepAlloc( 0, (Len+1)*sizeof(WCHAR));
|
|
|
|
if ( ProfileLocation == NULL ) {
|
|
|
|
Win32rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
} else {
|
|
|
|
swprintf(ProfileLocation, L"%s\\Security", SysRoot );
|
|
ProfileLocation[Len] = L'\0';
|
|
}
|
|
|
|
ScepFree(SysRoot);
|
|
|
|
} else
|
|
Win32rc = ERROR_INVALID_DATA;
|
|
}
|
|
|
|
if ( Win32rc == NO_ERROR ) {
|
|
|
|
#ifdef SCEJET_DBG
|
|
wprintf(L"Default location: %s\n", ProfileLocation);
|
|
#endif
|
|
//
|
|
// convert WCHAR into ANSI
|
|
//
|
|
memset(FileName, '\0', 512);
|
|
Win32rc = RtlNtStatusToDosError(
|
|
RtlUnicodeToMultiByteN(
|
|
(PCHAR)FileName,
|
|
512,
|
|
NULL,
|
|
ProfileLocation,
|
|
Len*sizeof(WCHAR)
|
|
));
|
|
|
|
if ( Win32rc == NO_ERROR ) {
|
|
//
|
|
// a backslash is required by Jet
|
|
//
|
|
strcat(FileName, "\\");
|
|
|
|
//
|
|
// set everyone change, admin full control to the directory
|
|
// the directory is created in the function.
|
|
//
|
|
Win32rc = ConvertTextSecurityDescriptor (
|
|
L"D:P(A;CIOI;GRGW;;;WD)(A;CIOI;GA;;;BA)(A;CIOI;GA;;;SY)",
|
|
&pSD,
|
|
&SDsize,
|
|
&SeInfo
|
|
);
|
|
if ( Win32rc == NO_ERROR ) {
|
|
|
|
ScepChangeAclRevision(pSD, ACL_REVISION);
|
|
|
|
rc = ScepCreateDirectory(
|
|
ProfileLocation,
|
|
TRUE, // a dir name
|
|
pSD // take parent's security setting
|
|
);
|
|
#ifdef SCEJET_DBG
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
wprintf(L"Cannot create directory %s\n", ProfileLocation );
|
|
#endif
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
__try {
|
|
|
|
JetErr = JetSetSystemParameter( hinstance, 0, JET_paramSystemPath, 0, (const char *)FileName );
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
//
|
|
// esent is not loaded
|
|
//
|
|
rc = SCESTATUS_MOD_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
JetErr = JetSetSystemParameter( hinstance, 0, JET_paramTempPath, 0, (const char *)FileName );
|
|
|
|
if ( JetErr == JET_errSuccess ) {
|
|
JetErr = JetSetSystemParameter( hinstance, 0, JET_paramLogFilePath, 0, (const char *)FileName );
|
|
|
|
if ( JetErr == JET_errSuccess ) {
|
|
JetErr = JetSetSystemParameter( hinstance, 0, JET_paramDatabasePageSize, 4096, NULL );
|
|
}
|
|
}
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// set log size to 1M
|
|
//
|
|
JetSetSystemParameter( hinstance, 0, JET_paramLogFileSize, 1024, NULL );
|
|
//
|
|
// defer the event log to when event log service is available
|
|
// (for example, in NT setup, there is no event log)
|
|
//
|
|
JetSetSystemParameter( hinstance, 0, JET_paramEventLogCache, 128, NULL );
|
|
|
|
JetSetSystemParameter( hinstance, 0, JET_paramMaxVerPages, 128, NULL );
|
|
|
|
//
|
|
// set minimize = maximum cache size to disable DBA in jet
|
|
// recommended setting for minimum is 4 * number of sessions
|
|
// maximum is up to the app (for performance)
|
|
//
|
|
|
|
JetSetSystemParameter( hinstance, 0, JET_paramMaxSessions, 64, NULL );
|
|
|
|
//
|
|
// performance is about 10% faster when using cache size 512 than 256
|
|
//
|
|
|
|
JetSetSystemParameter( hinstance, 0, JET_paramStartFlushThreshold, 50, NULL ); // sugguested by Exchange
|
|
JetSetSystemParameter( hinstance, 0, JET_paramStopFlushThreshold, 100, NULL ); // suggested by Exchange
|
|
|
|
//
|
|
// can't set to 512 because that's Jet's default value
|
|
// jet won't turn off DBA if value is set to 512.
|
|
//
|
|
JetSetSystemParameter( hinstance, 0, JET_paramCacheSizeMax, 496, NULL ); //256
|
|
|
|
JetSetSystemParameter( hinstance, 0, JET_paramCacheSizeMin, 496, NULL ); //256
|
|
|
|
//
|
|
// other system parameters, such as memory size in beta2
|
|
//
|
|
JetErr = JetSetSystemParameter( hinstance, 0, JET_paramCircularLog, 1, NULL );
|
|
|
|
JetErr = JetSetSystemParameter( hinstance, 0, JET_paramNoInformationEvent, 1, NULL );
|
|
|
|
}
|
|
}
|
|
|
|
ScepFree(pSD);
|
|
|
|
}
|
|
}
|
|
|
|
ScepFree(ProfileLocation);
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
rc = ScepDosErrorToSceStatus(Win32rc);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
|
|
SCESTATUS
|
|
SceJetGetTimeStamp(
|
|
IN PSCECONTEXT cxtProfile,
|
|
OUT PLARGE_INTEGER ConfigTimeStamp,
|
|
OUT PLARGE_INTEGER AnalyzeTimeStamp
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine queries the time stamp of last analysis.
|
|
|
|
The time stamp is saved in the "SmTblVersion" table.
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - The profile context
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_OTHER_ERROR
|
|
SCESTATUS from SceJetOpenTable
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
DWORD RetLen = 0;
|
|
|
|
if (cxtProfile == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
//
|
|
// Open version table
|
|
//
|
|
if ( ConfigTimeStamp != NULL ) {
|
|
|
|
rc = SceJetpGetValueFromVersion(
|
|
cxtProfile,
|
|
"SmTblVersion",
|
|
"ConfigTimeStamp",
|
|
(CHAR*)ConfigTimeStamp, //TimeStamp,
|
|
8, // 16, // number of bytes
|
|
&RetLen
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ||
|
|
rc == SCESTATUS_BUFFER_TOO_SMALL )
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
if ( RetLen < 8 ) {
|
|
(*ConfigTimeStamp).LowPart = 0;
|
|
(*ConfigTimeStamp).HighPart = 0;
|
|
}
|
|
}
|
|
|
|
if ( AnalyzeTimeStamp != NULL ) {
|
|
|
|
rc |= SceJetpGetValueFromVersion(
|
|
cxtProfile,
|
|
"SmTblVersion",
|
|
"AnalyzeTimeStamp",
|
|
(CHAR*)AnalyzeTimeStamp, //TimeStamp,
|
|
8, // 16, // number of bytes
|
|
&RetLen
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ||
|
|
rc == SCESTATUS_BUFFER_TOO_SMALL )
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
if ( RetLen < 8 ) {
|
|
(*AnalyzeTimeStamp).LowPart = 0;
|
|
(*AnalyzeTimeStamp).HighPart = 0;
|
|
}
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
|
|
SCESTATUS
|
|
SceJetSetTimeStamp(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN BOOL Flag,
|
|
IN LARGE_INTEGER NewTimeStamp
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine sets the time stamp (LARGE_INTEGER) of a analysis.
|
|
|
|
The time stamp is saved in the "SmTblVersion" table.
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - The profile context
|
|
|
|
Flag - indicates analyze or configure
|
|
Flag = TRUE - AnalyzeTimeStamp
|
|
Flag = FALSE - ConfigTimeStamp
|
|
|
|
NewTimeStamp - the new time stamp of a analysis
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_OTHER_ERROR
|
|
SCESTATUS from SceJetOpenTable
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
|
|
#ifdef SCE_JETDBG
|
|
CHAR CharTimeStamp[17];
|
|
|
|
sprintf(CharTimeStamp, "%08x%08x", NewTimeStamp.HighPart, NewTimeStamp.LowPart);
|
|
CharTimeStamp[16] = '\0';
|
|
|
|
printf("New time stamp is %s\n", CharTimeStamp);
|
|
#endif
|
|
|
|
if ( cxtProfile == NULL ) {
|
|
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
//
|
|
// set
|
|
//
|
|
if ( Flag ) {
|
|
|
|
rc = SceJetSetValueInVersion(
|
|
cxtProfile,
|
|
"SmTblVersion",
|
|
"AnalyzeTimeStamp",
|
|
(PWSTR)(&NewTimeStamp), //(PWSTR)CharTimeStamp,
|
|
8, // 16, // number of bytes
|
|
JET_prepReplace
|
|
);
|
|
} else {
|
|
|
|
rc = SceJetSetValueInVersion(
|
|
cxtProfile,
|
|
"SmTblVersion",
|
|
"ConfigTimeStamp",
|
|
(PWSTR)(&NewTimeStamp), //(PWSTR)CharTimeStamp,
|
|
8, // 16, // number of bytes
|
|
JET_prepReplace
|
|
);
|
|
}
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetGetDescription(
|
|
IN PSCECONTEXT cxtProfile,
|
|
OUT PWSTR *Description
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine queries the profile description from the "SmTblVersion" table.
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - The profile context
|
|
|
|
Description - The description buffer
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_OTHER_ERROR
|
|
SCESTATUS from SceJetOpenTable
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
DWORD RetLen = 0;
|
|
|
|
if ( cxtProfile == NULL || Description == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// Open version table
|
|
//
|
|
rc = SceJetpGetValueFromVersion(
|
|
cxtProfile,
|
|
"SmTblVersion",
|
|
"ProfileDescription",
|
|
NULL,
|
|
0, // number of bytes
|
|
&RetLen
|
|
);
|
|
|
|
if ( rc == SCESTATUS_BUFFER_TOO_SMALL ) {
|
|
|
|
*Description = (PWSTR)ScepAlloc( LPTR, RetLen+2 );
|
|
|
|
if ( *Description == NULL )
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
|
|
rc = SceJetpGetValueFromVersion(
|
|
cxtProfile,
|
|
"SmTblVersion",
|
|
"ProfileDescription",
|
|
(LPSTR)(*Description),
|
|
RetLen, // number of bytes
|
|
&RetLen
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepFree( *Description );
|
|
*Description = NULL;
|
|
}
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetpGetValueFromVersion(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN LPSTR TableName,
|
|
IN LPSTR ColumnName,
|
|
OUT LPSTR Value OPTIONAL,
|
|
IN DWORD ValueLen, // number of bytes
|
|
OUT PDWORD pRetLen
|
|
)
|
|
{
|
|
SCESTATUS rc;
|
|
JET_TABLEID TableID;
|
|
JET_ERR JetErr;
|
|
JET_COLUMNDEF ColumnDef;
|
|
|
|
//
|
|
// Open version table
|
|
//
|
|
rc = SceJetOpenTable(
|
|
cxtProfile,
|
|
TableName,
|
|
SCEJET_TABLE_VERSION,
|
|
SCEJET_OPEN_READ_ONLY,
|
|
&TableID
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// go to the first record
|
|
//
|
|
JetErr = JetMove(cxtProfile->JetSessionID,
|
|
TableID,
|
|
JET_MoveFirst,
|
|
0
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS) {
|
|
//
|
|
// get column ID for "Version"
|
|
//
|
|
JetErr = JetGetTableColumnInfo(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
ColumnName,
|
|
(VOID *)&ColumnDef,
|
|
sizeof(JET_COLUMNDEF),
|
|
0
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// retrieve the column
|
|
//
|
|
JetErr = JetRetrieveColumn(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
ColumnDef.columnid,
|
|
(void *)Value,
|
|
ValueLen,
|
|
pRetLen,
|
|
0,
|
|
NULL
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
}
|
|
JetCloseTable(cxtProfile->JetSessionID, TableID);
|
|
}
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetSetValueInVersion(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN LPSTR TableName,
|
|
IN LPSTR ColumnName,
|
|
IN PWSTR Value,
|
|
IN DWORD ValueLen, // number of bytes
|
|
IN DWORD Prep
|
|
)
|
|
{
|
|
SCESTATUS rc;
|
|
DWORD Len;
|
|
JET_TABLEID TableID;
|
|
JET_ERR JetErr;
|
|
JET_COLUMNDEF ColumnDef;
|
|
|
|
|
|
if ( cxtProfile == NULL || TableName == NULL || ColumnName == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// Open version table
|
|
//
|
|
rc = SceJetOpenTable(
|
|
cxtProfile,
|
|
TableName,
|
|
SCEJET_TABLE_VERSION,
|
|
SCEJET_OPEN_READ_WRITE, // read and write
|
|
&TableID
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// go to the first record
|
|
//
|
|
JetErr = JetMove(cxtProfile->JetSessionID,
|
|
TableID,
|
|
JET_MoveFirst,
|
|
0
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS) {
|
|
//
|
|
// get column ID for "Version"
|
|
//
|
|
JetErr = JetGetTableColumnInfo(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
ColumnName,
|
|
(VOID *)&ColumnDef,
|
|
sizeof(JET_COLUMNDEF),
|
|
0
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
JetErr = JetPrepareUpdate(cxtProfile->JetSessionID,
|
|
TableID,
|
|
Prep
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// set value
|
|
//
|
|
|
|
JetErr = JetSetColumn(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
ColumnDef.columnid,
|
|
(void *)Value,
|
|
ValueLen,
|
|
0, //JET_bitSetOverwriteLV,
|
|
NULL
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
//
|
|
// if setting fails, cancel the prepared record
|
|
//
|
|
JetPrepareUpdate( cxtProfile->JetSessionID,
|
|
TableID,
|
|
JET_prepCancel
|
|
);
|
|
} else {
|
|
|
|
//
|
|
// Setting columns succeed. Update the record
|
|
//
|
|
JetErr = JetUpdate( cxtProfile->JetSessionID,
|
|
TableID,
|
|
NULL,
|
|
0,
|
|
&Len
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
JetCloseTable(cxtProfile->JetSessionID, TableID);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetSeek(
|
|
IN PSCESECTION hSection,
|
|
IN PWSTR LinePrefix,
|
|
IN DWORD PrefixLength,
|
|
IN SCEJET_SEEK_FLAG SeekBit
|
|
)
|
|
{
|
|
PWSTR LwrPrefix=NULL;
|
|
SCESTATUS rc;
|
|
SCEJET_SEEK_FLAG NewSeekBit;
|
|
|
|
if ( hSection == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ( LinePrefix != NULL && SeekBit > SCEJET_SEEK_GE ) {
|
|
//
|
|
// do lowercase search
|
|
//
|
|
LwrPrefix = (PWSTR)ScepAlloc(0, PrefixLength+sizeof(WCHAR));
|
|
|
|
if ( LwrPrefix == NULL ) {
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
|
|
} else {
|
|
wcscpy(LwrPrefix, LinePrefix);
|
|
LwrPrefix = _wcslwr(LwrPrefix);
|
|
|
|
switch ( SeekBit ) {
|
|
case SCEJET_SEEK_GT_NO_CASE:
|
|
NewSeekBit = SCEJET_SEEK_GT;
|
|
break;
|
|
case SCEJET_SEEK_EQ_NO_CASE:
|
|
NewSeekBit = SCEJET_SEEK_EQ;
|
|
break;
|
|
default:
|
|
NewSeekBit = SCEJET_SEEK_GE;
|
|
break;
|
|
}
|
|
|
|
rc = SceJetJetErrorToSceStatus(
|
|
SceJetpSeek(
|
|
hSection,
|
|
LwrPrefix,
|
|
PrefixLength,
|
|
NewSeekBit,
|
|
(SeekBit == SCEJET_SEEK_GE_DONT_CARE)
|
|
));
|
|
ScepFree(LwrPrefix);
|
|
}
|
|
} else {
|
|
//
|
|
// do case sensitive search, or NULL search
|
|
//
|
|
rc = SceJetJetErrorToSceStatus(
|
|
SceJetpSeek(
|
|
hSection,
|
|
LinePrefix,
|
|
PrefixLength,
|
|
SeekBit,
|
|
FALSE
|
|
));
|
|
}
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
SCESTATUS
|
|
SceJetMoveNext(
|
|
IN PSCESECTION hSection
|
|
)
|
|
{
|
|
JET_ERR JetErr;
|
|
INT Result;
|
|
|
|
if ( hSection == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// skip deleted records
|
|
//
|
|
do {
|
|
JetErr = JetMove(hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
JET_MoveNext,
|
|
0
|
|
);
|
|
if ( JetErr == JET_errSuccess ) {
|
|
// compare section ID
|
|
JetErr = SceJetpCompareLine(
|
|
hSection,
|
|
JET_bitSeekGE,
|
|
NULL,
|
|
0,
|
|
&Result,
|
|
NULL
|
|
);
|
|
if ( JetErr == JET_errSuccess && Result != 0 )
|
|
JetErr = JET_errRecordNotFound;
|
|
|
|
}
|
|
|
|
} while ( JetErr == JET_errRecordDeleted );
|
|
|
|
|
|
return(SceJetJetErrorToSceStatus(JetErr));
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
SCESTATUS
|
|
SceJetRenameLine(
|
|
IN PSCESECTION hSection,
|
|
IN PWSTR Name,
|
|
IN PWSTR NewName,
|
|
IN BOOL bReserveCase
|
|
)
|
|
{
|
|
PWSTR LwrName=NULL;
|
|
DWORD Len;
|
|
JET_ERR JetErr;
|
|
JET_SETINFO SetInfo;
|
|
|
|
|
|
if ( !hSection || !Name || !NewName ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
Len = wcslen(NewName)*sizeof(WCHAR);
|
|
|
|
if ( Len <= 0 ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ( bReserveCase ) {
|
|
LwrName = NewName;
|
|
|
|
} else {
|
|
//
|
|
// lower cased
|
|
//
|
|
LwrName = (PWSTR)ScepAlloc(0, Len+2);
|
|
if ( LwrName == NULL ) {
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
}
|
|
wcscpy(LwrName, NewName);
|
|
LwrName = _wcslwr(LwrName);
|
|
|
|
}
|
|
|
|
SetInfo.cbStruct = sizeof(JET_SETINFO);
|
|
SetInfo.itagSequence = 1;
|
|
SetInfo.ibLongValue = 0;
|
|
|
|
//
|
|
// check to see if the same key name already exists
|
|
//
|
|
JetErr = SceJetSeek(
|
|
hSection,
|
|
Name,
|
|
wcslen(Name)*sizeof(WCHAR),
|
|
SCEJET_SEEK_EQ_NO_CASE
|
|
);
|
|
|
|
if ( JetErr == JET_errSuccess ) {
|
|
//
|
|
// find a match. overwrite the value
|
|
//
|
|
JetErr = JetBeginTransaction(hSection->JetSessionID);
|
|
|
|
if ( JetErr == JET_errSuccess ) {
|
|
JetErr = JetPrepareUpdate(hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
JET_prepReplace
|
|
);
|
|
if ( JetErr == JET_errSuccess ) {
|
|
//
|
|
// set the new key in "Name" column
|
|
//
|
|
JetErr = JetSetColumn(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
hSection->JetColumnNameID,
|
|
(void *)LwrName,
|
|
Len,
|
|
JET_bitSetOverwriteLV,
|
|
&SetInfo
|
|
);
|
|
}
|
|
|
|
if ( JET_errSuccess == JetErr ) {
|
|
//
|
|
// commit the transaction
|
|
//
|
|
JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
|
|
} else {
|
|
//
|
|
// rollback the transaction
|
|
//
|
|
JetRollback(hSection->JetSessionID,0);
|
|
}
|
|
JetPrepareUpdate(hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
JET_prepCancel
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( LwrName != NewName ) {
|
|
ScepFree(LwrName);
|
|
}
|
|
|
|
return( SceJetJetErrorToSceStatus(JetErr) );
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
SCESTATUS
|
|
SceJetRenameLine(
|
|
IN PSCESECTION hSection,
|
|
IN PWSTR Name,
|
|
IN PWSTR NewName,
|
|
IN BOOL bReserveCase
|
|
)
|
|
{
|
|
PWSTR Value=NULL;
|
|
DWORD ValueLen;
|
|
SCESTATUS rc;
|
|
JET_ERR JetErr;
|
|
|
|
|
|
if ( !hSection || !Name || !NewName ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_EXACT_MATCH_NO_CASE,
|
|
Name,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&ValueLen
|
|
);
|
|
|
|
if ( SCESTATUS_SUCCESS == rc ) {
|
|
//
|
|
// continue only when this record is found.
|
|
//
|
|
if ( ValueLen ) {
|
|
Value = (PWSTR)ScepAlloc(0, ValueLen+2);
|
|
|
|
if ( Value ) {
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CURRENT,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
Value,
|
|
ValueLen,
|
|
&ValueLen
|
|
);
|
|
} else
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
}
|
|
|
|
if ( SCESTATUS_SUCCESS == rc ) {
|
|
|
|
JetErr = JetBeginTransaction(hSection->JetSessionID);
|
|
|
|
if ( JetErr == JET_errSuccess ) {
|
|
//
|
|
// now delete this line
|
|
//
|
|
rc = SceJetDelete(hSection, NULL, FALSE, SCEJET_DELETE_LINE);
|
|
|
|
if ( SCESTATUS_SUCCESS == rc ) {
|
|
//
|
|
// add the new line in.
|
|
//
|
|
rc = SceJetSetLine(
|
|
hSection,
|
|
NewName,
|
|
bReserveCase,
|
|
Value,
|
|
ValueLen,
|
|
0
|
|
);
|
|
}
|
|
|
|
if ( SCESTATUS_SUCCESS == rc ) {
|
|
//
|
|
// commit the transaction
|
|
//
|
|
JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
|
|
} else {
|
|
//
|
|
// rollback the transaction
|
|
//
|
|
JetRollback(hSection->JetSessionID,0);
|
|
}
|
|
} else
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
}
|
|
}
|
|
|
|
return( rc );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// Helpers
|
|
//
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
VOID
|
|
SceJetInitializeData()
|
|
//
|
|
// only be called during server initialization code
|
|
//
|
|
{
|
|
JetInited = FALSE;
|
|
JetInstance = 0;
|
|
}
|
|
|
|
SCESTATUS
|
|
SceJetInitialize(
|
|
OUT JET_ERR *pJetErr OPTIONAL
|
|
)
|
|
/*
|
|
Routine Description:
|
|
|
|
Initialize jet engine for sce server
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS
|
|
*/
|
|
{
|
|
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
JET_ERR JetErr=0;
|
|
|
|
//
|
|
// cancel any pending timer queue
|
|
//
|
|
ScepServerCancelTimer();
|
|
|
|
EnterCriticalSection(&JetSync);
|
|
|
|
if ( !JetInited ) {
|
|
|
|
//
|
|
// set system configuration for Jet engine
|
|
//
|
|
rc = SceJetpConfigJetSystem( &JetInstance);
|
|
if ( SCESTATUS_SUCCESS == rc ) {
|
|
|
|
//
|
|
// initialize jet engine
|
|
//
|
|
__try {
|
|
|
|
JetErr = JetInit(&JetInstance);
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( JetErr == JET_errSuccess ) {
|
|
|
|
JetInited = TRUE;
|
|
|
|
//
|
|
// if failed to initialize Jet writer (for backup/restore)
|
|
// don't fail the engine
|
|
//
|
|
} else {
|
|
|
|
//
|
|
// this will happen only if jet cannot recover the
|
|
// database by itself (JetInit() claims to attempt recovery only)
|
|
// repair might help - so only spew out a message advising the user
|
|
//
|
|
// map error so setup/policy propagation clients
|
|
// can log events
|
|
//
|
|
|
|
// if ( SCE_JET_CORRUPTION_ERROR(JetErr) ) {
|
|
|
|
rc = SCESTATUS_JET_DATABASE_ERROR;
|
|
|
|
ScepLogOutput3(0, ERROR_DATABASE_FAILURE, SCEDLL_ERROR_RECOVER_DB );
|
|
// }
|
|
JetInstance = 0;
|
|
}
|
|
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
//
|
|
// for some reason, esent is not loaded
|
|
//
|
|
rc = SCESTATUS_MOD_NOT_FOUND;
|
|
JetInstance = 0;
|
|
}
|
|
|
|
} else {
|
|
JetInstance = 0;
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&JetSync);
|
|
|
|
if ( pJetErr ) *pJetErr = JetErr;
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetTerminate(BOOL bCleanVs)
|
|
/*
|
|
Routine Description:
|
|
|
|
Terminate jet engine
|
|
|
|
Arguments:
|
|
|
|
bCleanVs - if to clean up the version store completely
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS
|
|
*/
|
|
{
|
|
|
|
EnterCriticalSection(&JetSync);
|
|
|
|
//
|
|
// destroy the jet backup/restore writer
|
|
//
|
|
if ( JetInited || JetInstance ) {
|
|
|
|
if ( bCleanVs ) {
|
|
//
|
|
// clean up version store
|
|
//
|
|
JetTerm2(JetInstance, JET_bitTermComplete);
|
|
} else {
|
|
//
|
|
// do not clean up version store
|
|
//
|
|
JetTerm(JetInstance);
|
|
}
|
|
JetInstance = 0;
|
|
JetInited = FALSE;
|
|
}
|
|
|
|
LeaveCriticalSection(&JetSync);
|
|
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
SCESTATUS
|
|
SceJetTerminateNoCritical(BOOL bCleanVs)
|
|
/*
|
|
Routine Description:
|
|
|
|
Terminate jet engine, NOT critical sectioned!!!
|
|
|
|
Arguments:
|
|
|
|
bCleanVs - if to clean up the version store completely
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS
|
|
*/
|
|
{
|
|
//
|
|
// the critical section is entered outside of this function
|
|
//
|
|
// destroy the jet backup/restore writer
|
|
//
|
|
if ( JetInited || JetInstance ) {
|
|
|
|
if ( bCleanVs ) {
|
|
//
|
|
// clean up version store
|
|
//
|
|
JetTerm2(JetInstance, JET_bitTermComplete);
|
|
} else {
|
|
//
|
|
// do not clean up version store
|
|
//
|
|
JetTerm(JetInstance);
|
|
}
|
|
JetInstance = 0;
|
|
JetInited = FALSE;
|
|
}
|
|
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetStartTransaction(
|
|
IN PSCECONTEXT cxtProfile
|
|
)
|
|
/*
|
|
Routine Description:
|
|
|
|
Start a transaction on the session
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - the database context
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS
|
|
*/
|
|
{
|
|
JET_ERR JetErr;
|
|
|
|
if ( cxtProfile == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
JetErr = JetBeginTransaction( cxtProfile->JetSessionID);
|
|
|
|
return( SceJetJetErrorToSceStatus(JetErr));
|
|
|
|
}
|
|
|
|
SCESTATUS
|
|
SceJetCommitTransaction(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN JET_GRBIT grbit
|
|
)
|
|
/*
|
|
Routine Description:
|
|
|
|
Commit a transaction on the session
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - the database context
|
|
|
|
grbit - flag for the commission
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS
|
|
*/
|
|
{
|
|
JET_ERR JetErr;
|
|
|
|
if ( cxtProfile == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
JetErr = JetCommitTransaction(cxtProfile->JetSessionID, grbit );
|
|
|
|
return( SceJetJetErrorToSceStatus(JetErr) );
|
|
|
|
}
|
|
|
|
SCESTATUS
|
|
SceJetRollback(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN JET_GRBIT grbit
|
|
)
|
|
/*
|
|
Routine Description:
|
|
|
|
Rollback a transaction on the session
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - the database context
|
|
|
|
grbit - the flag for transaction rollback
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS
|
|
*/
|
|
{
|
|
JET_ERR JetErr;
|
|
|
|
if ( cxtProfile == NULL )
|
|
return(SCESTATUS_SUCCESS);
|
|
|
|
__try {
|
|
JetErr = JetRollback(cxtProfile->JetSessionID, grbit);
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
JetErr = JET_errOutOfMemory;
|
|
}
|
|
return( SceJetJetErrorToSceStatus(JetErr) );
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
SceJetDeleteJetFiles(
|
|
IN PWSTR DbFileName
|
|
)
|
|
{
|
|
TCHAR TempFileName[MAX_PATH];
|
|
PWSTR SysRoot=NULL;
|
|
DWORD SysLen;
|
|
DWORD rc;
|
|
intptr_t hFile;
|
|
struct _wfinddata_t fInfo;
|
|
|
|
|
|
BOOL bRet = FALSE;
|
|
|
|
EnterCriticalSection(&JetSync);
|
|
|
|
if ( JetInited == FALSE ) {
|
|
|
|
SysLen = 0;
|
|
rc = ScepGetNTDirectory( &SysRoot, &SysLen, SCE_FLAG_WINDOWS_DIR );
|
|
|
|
if ( rc == NO_ERROR && SysRoot != NULL ) {
|
|
|
|
swprintf(TempFileName, L"%s\\Security\\res1.log\0", SysRoot);
|
|
TempFileName[MAX_PATH-1] = L'\0';
|
|
|
|
DeleteFile(TempFileName);
|
|
|
|
swprintf(TempFileName, L"%s\\Security\\res2.log\0", SysRoot);
|
|
TempFileName[MAX_PATH-1] = L'\0';
|
|
|
|
DeleteFile(TempFileName);
|
|
|
|
//
|
|
// delete edb files
|
|
//
|
|
swprintf(TempFileName, L"%s\\Security\\edb*.*\0", SysRoot);
|
|
TempFileName[MAX_PATH-1] = L'\0';
|
|
|
|
hFile = _wfindfirst(TempFileName, &fInfo);
|
|
|
|
if ( hFile != -1 ) {
|
|
|
|
do {
|
|
|
|
swprintf(TempFileName, L"%s\\Security\\%s\0", SysRoot, fInfo.name);
|
|
TempFileName[MAX_PATH-1] = L'\0';
|
|
|
|
DeleteFile(TempFileName);
|
|
|
|
} while ( _wfindnext(hFile, &fInfo) == 0 );
|
|
|
|
_findclose(hFile);
|
|
}
|
|
|
|
//
|
|
// delete temp files
|
|
//
|
|
swprintf(TempFileName, L"%s\\Security\\tmp*.edb\0", SysRoot);
|
|
TempFileName[MAX_PATH-1] = L'\0';
|
|
|
|
hFile = _wfindfirst(TempFileName, &fInfo);
|
|
|
|
if ( hFile != -1 ) {
|
|
|
|
do {
|
|
|
|
swprintf(TempFileName, L"%s\\Security\\%s\0", SysRoot, fInfo.name);
|
|
TempFileName[MAX_PATH-1] = L'\0';
|
|
|
|
DeleteFile(TempFileName);
|
|
|
|
} while ( _wfindnext(hFile, &fInfo) == 0 );
|
|
|
|
_findclose(hFile);
|
|
}
|
|
|
|
ScepFree(SysRoot);
|
|
|
|
//
|
|
// delete the database file if it's passed in.
|
|
//
|
|
if ( DbFileName ) {
|
|
DeleteFile(DbFileName);
|
|
}
|
|
|
|
bRet = TRUE;
|
|
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&JetSync);
|
|
|
|
return(bRet);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetSetCurrentLine(
|
|
IN PSCESECTION hSection,
|
|
IN PWSTR Value,
|
|
IN DWORD ValueLen
|
|
)
|
|
/* ++
|
|
Fucntion Description:
|
|
|
|
This routine writes the Value to the current line in section (hSection).
|
|
Make sure the cursor is on the right line before calling this API
|
|
|
|
Arguments:
|
|
|
|
hSection - The context handle of the section
|
|
|
|
Value - The info set to Column "Value"
|
|
|
|
ValueLen - The size of the value field.
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_OTHER_ERROR
|
|
SCESTATUS_ACCESS_DENIED
|
|
SCESTATUS_DATA_OVERFLOW
|
|
|
|
-- */
|
|
{
|
|
JET_ERR JetErr;
|
|
DWORD Len;
|
|
SCESTATUS rc;
|
|
DWORD prep;
|
|
JET_SETINFO SetInfo;
|
|
|
|
if ( hSection == NULL ||
|
|
Value == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
SetInfo.cbStruct = sizeof(JET_SETINFO);
|
|
SetInfo.itagSequence = 1;
|
|
SetInfo.ibLongValue = 0;
|
|
|
|
prep = JET_prepReplace;
|
|
|
|
JetErr = JetBeginTransaction(hSection->JetSessionID);
|
|
|
|
if ( JetErr == JET_errSuccess ) {
|
|
JetErr = JetPrepareUpdate(hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
prep
|
|
);
|
|
if ( JetErr != JET_errSuccess ) {
|
|
//
|
|
// rollback the transaction
|
|
//
|
|
JetRollback(hSection->JetSessionID,0);
|
|
}
|
|
}
|
|
|
|
if ( JetErr != JET_errSuccess)
|
|
return(SceJetJetErrorToSceStatus(JetErr));
|
|
|
|
|
|
//
|
|
// set value column
|
|
//
|
|
|
|
JetErr = JetSetColumn(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
hSection->JetColumnValueID,
|
|
(void *)Value,
|
|
ValueLen,
|
|
0, //JET_bitSetOverwriteLV,
|
|
&SetInfo
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( JetErr == JET_errSuccess ) {
|
|
//
|
|
// Setting columns succeed. Update the record
|
|
//
|
|
JetErr = JetUpdate(hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
NULL,
|
|
0,
|
|
&Len
|
|
);
|
|
} else {
|
|
goto CleanUp;
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS )
|
|
JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
|
|
|
|
CleanUp:
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
//
|
|
// if setting fails, cancel the prepared record
|
|
//
|
|
JetPrepareUpdate(hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
JET_prepCancel
|
|
);
|
|
//
|
|
// Rollback the transaction
|
|
//
|
|
JetRollback(hSection->JetSessionID,0);
|
|
|
|
}
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
ScepIsValidContext(
|
|
PSCECONTEXT context
|
|
)
|
|
{
|
|
if ( context == NULL ) {
|
|
return FALSE;
|
|
}
|
|
|
|
__try {
|
|
|
|
if ( (context->Type & 0xFFFFFF02L) == 0xFFFFFF02L ) {
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
LONG
|
|
SceJetGetGpoIDByName(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN PWSTR szGpoName,
|
|
IN BOOL bAdd
|
|
)
|
|
/*
|
|
Routine Description:
|
|
|
|
Search for a GPO by name in the GPO table. If bAdd is TRUE and the GPO name
|
|
is not found, it will be added to the GPO table
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - the database handle
|
|
|
|
szGpoName - the GPO name
|
|
|
|
bAdd - TRUE to add the GPO name to the GPO table if it's not found
|
|
|
|
Return Value:
|
|
|
|
The GPO ID. If -1 is returned, GetLastError to get the SCE error code.
|
|
|
|
*/
|
|
{
|
|
|
|
|
|
SCESTATUS rc;
|
|
JET_ERR JetErr;
|
|
DWORD Actual;
|
|
PWSTR LwrName=NULL;
|
|
DWORD Len;
|
|
|
|
if ( cxtProfile == NULL || szGpoName == NULL ||
|
|
szGpoName[0] == L'\0' ) {
|
|
|
|
SetLastError(SCESTATUS_INVALID_PARAMETER);
|
|
return (-1);
|
|
}
|
|
|
|
JET_TABLEID TableID;
|
|
|
|
rc = SceJetOpenTable(
|
|
cxtProfile,
|
|
"SmTblGpo",
|
|
SCEJET_TABLE_GPO,
|
|
bAdd ? SCEJET_OPEN_READ_WRITE : SCEJET_OPEN_READ_ONLY,
|
|
&TableID
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
SetLastError(rc);
|
|
return(-1);
|
|
}
|
|
|
|
JET_COLUMNDEF ColumnDef;
|
|
LONG GpoID = 0;
|
|
|
|
JetErr = JetGetTableColumnInfo(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
"GpoID",
|
|
(VOID *)&ColumnDef,
|
|
sizeof(JET_COLUMNDEF),
|
|
JET_ColInfo
|
|
);
|
|
|
|
if ( JET_errSuccess == JetErr ) {
|
|
|
|
//
|
|
// set current index to SectionKey (the name)
|
|
//
|
|
JetErr = JetSetCurrentIndex(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
"GpoName"
|
|
);
|
|
|
|
}
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// search for the name
|
|
//
|
|
Len = wcslen(szGpoName);
|
|
LwrName = (PWSTR)ScepAlloc(0, (Len+1)*sizeof(WCHAR));
|
|
|
|
if ( LwrName != NULL ) {
|
|
|
|
wcscpy(LwrName, szGpoName);
|
|
LwrName = _wcslwr(LwrName);
|
|
|
|
JetErr = JetMakeKey(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
(VOID *)LwrName,
|
|
Len*sizeof(WCHAR),
|
|
JET_bitNewKey
|
|
);
|
|
|
|
if ( JetErr == JET_errKeyIsMade ) {
|
|
//
|
|
// Only one key is needed, it may return this code, even on success.
|
|
//
|
|
JetErr = JET_errSuccess;
|
|
}
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
JetErr = JetSeek(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
JET_bitSeekEQ
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// find the Gpo name, retrieve gpo id
|
|
//
|
|
JetErr = JetRetrieveColumn(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
ColumnDef.columnid,
|
|
(void *)&GpoID,
|
|
4,
|
|
&Actual,
|
|
0,
|
|
NULL
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
} else if ( SCESTATUS_RECORD_NOT_FOUND == rc ) {
|
|
|
|
GpoID = 0;
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
if ( bAdd ) {
|
|
|
|
//
|
|
// if not found and add is requested
|
|
//
|
|
rc = SceJetpAddGpo(cxtProfile,
|
|
TableID,
|
|
ColumnDef.columnid,
|
|
LwrName,
|
|
&GpoID
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ScepFree(LwrName);
|
|
|
|
} else
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
}
|
|
|
|
JetCloseTable( cxtProfile->JetSessionID, TableID );
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
SetLastError(rc);
|
|
GpoID = -1;
|
|
}
|
|
|
|
return(GpoID);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetGetGpoNameByID(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN LONG GpoID,
|
|
OUT PWSTR Name OPTIONAL,
|
|
IN OUT LPDWORD pNameLen,
|
|
OUT PWSTR DisplayName OPTIONAL,
|
|
IN OUT LPDWORD pDispNameLen
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine retrieve the GPO name for the ID in the GPO table.
|
|
If Name is NULL, this routine really does a seek by ID. The cursor will
|
|
be on the record if there is a successful match.
|
|
|
|
Arguments:
|
|
|
|
cxtProfile - The profile context handle
|
|
|
|
GpoID - The GPO ID looking for
|
|
|
|
Name - The optional output buffer for section name
|
|
|
|
pNameLen - The name buffer's length
|
|
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_RECORD_NOT_FOUND
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_OTHER_ERROR
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
JET_ERR JetErr;
|
|
DWORD Actual;
|
|
|
|
|
|
if ( cxtProfile == NULL ||
|
|
( pDispNameLen == NULL && pNameLen == NULL) ) {
|
|
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ( GpoID <= 0 ) {
|
|
return(SCESTATUS_RECORD_NOT_FOUND);
|
|
}
|
|
|
|
//
|
|
// reset buffers
|
|
//
|
|
if ( Name == NULL && pNameLen ) {
|
|
*pNameLen = 0;
|
|
}
|
|
|
|
if ( DisplayName == NULL && pDispNameLen ) {
|
|
*pDispNameLen = 0;
|
|
}
|
|
|
|
JET_TABLEID TableID=0;
|
|
|
|
//
|
|
// Open GPO table
|
|
//
|
|
rc = SceJetOpenTable(
|
|
cxtProfile,
|
|
"SmTblGpo",
|
|
SCEJET_TABLE_GPO,
|
|
SCEJET_OPEN_READ_ONLY,
|
|
&TableID
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
//
|
|
// set current index to SecID (the ID)
|
|
//
|
|
JetErr = JetSetCurrentIndex(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
"SectionKey"
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
JetErr = JetMakeKey(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
(void *)(&GpoID),
|
|
4,
|
|
JET_bitNewKey
|
|
);
|
|
|
|
if ( JetErr == JET_errKeyIsMade ) {
|
|
//
|
|
// Only one key is needed, it may return this code, even on success.
|
|
//
|
|
JetErr = JET_errSuccess;
|
|
}
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
JetErr = JetSeek(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
JET_bitSeekEQ
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
//
|
|
// find the GPO ID, retrieve column Name if requested
|
|
//
|
|
|
|
if ( pNameLen != NULL ) {
|
|
|
|
JET_COLUMNDEF ColumnDef;
|
|
|
|
JetErr = JetGetTableColumnInfo(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
"Name",
|
|
(VOID *)&ColumnDef,
|
|
sizeof(JET_COLUMNDEF),
|
|
JET_ColInfo
|
|
);
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( SCESTATUS_SUCCESS == rc ) {
|
|
|
|
JetErr = JetRetrieveColumn(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
ColumnDef.columnid,
|
|
(void *)Name,
|
|
*pNameLen,
|
|
&Actual,
|
|
0,
|
|
NULL
|
|
);
|
|
*pNameLen = Actual;
|
|
}
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
|
|
//
|
|
// retrieve column DisplayName if requested
|
|
//
|
|
|
|
if ( ( SCESTATUS_SUCCESS == rc) &&
|
|
( pDispNameLen != NULL) ) {
|
|
|
|
JET_COLUMNDEF ColumnDef;
|
|
|
|
JetErr = JetGetTableColumnInfo(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
"DisplayName",
|
|
(VOID *)&ColumnDef,
|
|
sizeof(JET_COLUMNDEF),
|
|
JET_ColInfo
|
|
);
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( SCESTATUS_SUCCESS == rc ) {
|
|
|
|
JetErr = JetRetrieveColumn(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
ColumnDef.columnid,
|
|
(void *)DisplayName,
|
|
*pDispNameLen,
|
|
&Actual,
|
|
0,
|
|
NULL
|
|
);
|
|
*pDispNameLen = Actual;
|
|
}
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
JetCloseTable( cxtProfile->JetSessionID, TableID);
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceJetpAddGpo(
|
|
IN PSCECONTEXT cxtProfile,
|
|
IN JET_TABLEID TableID,
|
|
IN JET_COLUMNID GpoIDColumnID,
|
|
IN PCWSTR Name,
|
|
OUT LONG *pGpoID
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
JET_ERR JetErr;
|
|
DWORD Len;
|
|
|
|
if ( cxtProfile == NULL ||
|
|
Name == NULL ||
|
|
pGpoID == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
*pGpoID = 0;
|
|
|
|
//
|
|
// get the next available GPO ID first.
|
|
// set current index to the ID
|
|
//
|
|
JetErr = JetSetCurrentIndex(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
"SectionKey"
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
//
|
|
// Move to the last record
|
|
//
|
|
JetErr = JetMove(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
JET_MoveLast,
|
|
0
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// find the GPO ID, retrieve column Name
|
|
//
|
|
JetErr = JetRetrieveColumn(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
GpoIDColumnID,
|
|
(void *)pGpoID,
|
|
4,
|
|
&Len,
|
|
0,
|
|
NULL
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// The next available ID is current ID + 1
|
|
//
|
|
*pGpoID = *pGpoID + 1;
|
|
}
|
|
|
|
} else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
|
|
*pGpoID = 1;
|
|
rc = SCESTATUS_SUCCESS;
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// add a record to the GPO table
|
|
//
|
|
JetErr = JetPrepareUpdate(cxtProfile->JetSessionID,
|
|
TableID,
|
|
JET_prepInsert
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// set GpoID
|
|
//
|
|
|
|
JetErr = JetSetColumn(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
GpoIDColumnID,
|
|
(void *)pGpoID,
|
|
4,
|
|
0, //JET_bitSetOverwriteLV,
|
|
NULL
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// set Name column
|
|
//
|
|
|
|
JET_COLUMNDEF ColumnDef;
|
|
|
|
JetErr = JetGetTableColumnInfo(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
"Name",
|
|
(VOID *)&ColumnDef,
|
|
sizeof(JET_COLUMNDEF),
|
|
JET_ColInfo
|
|
);
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
|
|
if ( SCESTATUS_SUCCESS == rc ) {
|
|
|
|
Len = wcslen(Name)*sizeof(WCHAR);
|
|
|
|
JetErr = JetSetColumn(
|
|
cxtProfile->JetSessionID,
|
|
TableID,
|
|
ColumnDef.columnid,
|
|
(void *)Name,
|
|
Len,
|
|
0,
|
|
NULL
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
|
|
}
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
//
|
|
// if setting fails, cancel the prepared record
|
|
//
|
|
JetPrepareUpdate( cxtProfile->JetSessionID,
|
|
TableID,
|
|
JET_prepCancel
|
|
);
|
|
} else {
|
|
|
|
//
|
|
// Setting columns succeed. Update the record
|
|
//
|
|
JetErr = JetUpdate(cxtProfile->JetSessionID,
|
|
TableID,
|
|
NULL,
|
|
0,
|
|
&Len
|
|
);
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
//
|
|
// request the GPO ID (if there is any) for the object
|
|
//
|
|
SCESTATUS
|
|
SceJetGetGpoID(
|
|
IN PSCESECTION hSection,
|
|
IN PWSTR ObjectName,
|
|
IN JET_COLUMNID JetColGpoID OPTIONAL,
|
|
OUT LONG *pGpoID
|
|
)
|
|
{
|
|
if ( hSection == NULL || ObjectName == NULL || pGpoID == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
SCESTATUS rc;
|
|
|
|
*pGpoID = 0;
|
|
|
|
JET_COLUMNID ColGpoID = 0;
|
|
|
|
if ( JetColGpoID == 0 ) {
|
|
|
|
ColGpoID = hSection->JetColumnGpoID;
|
|
} else {
|
|
ColGpoID = JetColGpoID;
|
|
}
|
|
|
|
if ( ColGpoID > 0 ) {
|
|
|
|
rc = SceJetSeek(
|
|
hSection,
|
|
ObjectName,
|
|
wcslen(ObjectName)*sizeof(WCHAR),
|
|
SCEJET_SEEK_EQ_NO_CASE
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
DWORD Actual;
|
|
JET_ERR JetErr;
|
|
|
|
JetErr = JetRetrieveColumn(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
ColGpoID,
|
|
(void *)pGpoID,
|
|
4,
|
|
&Actual,
|
|
0,
|
|
NULL
|
|
);
|
|
if ( JET_errSuccess != JetErr ) {
|
|
//
|
|
// if the column is nil (no value), it will return warning
|
|
// but the buffer pGpoID is trashed
|
|
//
|
|
*pGpoID = 0;
|
|
}
|
|
|
|
rc = SceJetJetErrorToSceStatus(JetErr);
|
|
}
|
|
|
|
} else {
|
|
rc = SCESTATUS_RECORD_NOT_FOUND;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|