Leaked source code of windows server 2003
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.

6538 lines
176 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. scejet.c
  5. Abstract:
  6. Sce-Jet service APIs
  7. Author:
  8. Jin Huang (jinhuang) 13-Jan-1997
  9. Revision History:
  10. --*/
  11. #include "serverp.h"
  12. #include <io.h>
  13. #include <objbase.h>
  14. #include <initguid.h>
  15. #include <crtdbg.h>
  16. #include <stddef.h>
  17. #include <atlconv.h>
  18. #include <atlbase.h>
  19. //#define SCEJET_DBG 1
  20. //
  21. // should be controlled by critical section for static variables
  22. //
  23. static JET_INSTANCE JetInstance=0;
  24. static BOOL JetInited=FALSE;
  25. static BOOL JetInitAttempted=FALSE;
  26. extern CRITICAL_SECTION JetSync;
  27. #define SCE_JET_CORRUPTION_ERROR(Err) (Err == JET_errDatabaseCorrupted ||\
  28. Err == JET_errDiskIO ||\
  29. Err == JET_errReadVerifyFailure ||\
  30. Err == JET_errBadPageLink ||\
  31. Err == JET_errDbTimeCorrupted ||\
  32. Err == JET_errLogFileCorrupt ||\
  33. Err == JET_errCheckpointCorrupt ||\
  34. Err == JET_errLogCorruptDuringHardRestore ||\
  35. Err == JET_errLogCorruptDuringHardRecovery ||\
  36. Err == JET_errCatalogCorrupted ||\
  37. Err == JET_errDatabaseDuplicate)
  38. DEFINE_GUID(CLSID_SceWriter,0x9cb9311a, 0x6b16, 0x4d5c, 0x85, 0x3e, 0x53, 0x79, 0x81, 0x38, 0xd5, 0x51);
  39. // 9cb9311a-6b16-4d5c-853e-53798138d551
  40. typedef struct _FIND_CONTEXT_ {
  41. DWORD Length;
  42. WCHAR Prefix[SCEJET_PREFIX_MAXLEN];
  43. } SCEJET_FIND_CONTEXT;
  44. //
  45. // each thread has its own FindContext
  46. //
  47. SCEJET_FIND_CONTEXT Thread FindContext;
  48. JET_ERR
  49. SceJetpSeek(
  50. IN PSCESECTION hSection,
  51. IN PWSTR LinePrefix,
  52. IN DWORD PrefixLength,
  53. IN SCEJET_SEEK_FLAG SeekBit,
  54. IN BOOL bOkNoMatch
  55. );
  56. JET_ERR
  57. SceJetpCompareLine(
  58. IN PSCESECTION hSection,
  59. IN JET_GRBIT grbit,
  60. IN PWSTR LinePrefix OPTIONAL,
  61. IN DWORD PrefixLength,
  62. OUT INT *Result,
  63. OUT DWORD *ActualLength OPTIONAL
  64. );
  65. JET_ERR
  66. SceJetpMakeKey(
  67. IN JET_SESID SessionID,
  68. IN JET_TABLEID TableID,
  69. IN DOUBLE SectionID,
  70. IN PWSTR LinePrefix,
  71. IN DWORD PrefixLength
  72. );
  73. JET_ERR
  74. SceJetpBuildUpperLimit(
  75. IN PSCESECTION hSection,
  76. IN PWSTR LinePrefix,
  77. IN DWORD Len,
  78. IN BOOL bReserveCase
  79. );
  80. SCESTATUS
  81. SceJetpGetAvailableSectionID(
  82. IN PSCECONTEXT cxtProfile,
  83. OUT DOUBLE *SectionID
  84. );
  85. SCESTATUS
  86. SceJetpAddAllSections(
  87. IN PSCECONTEXT cxtProfile
  88. );
  89. SCESTATUS
  90. SceJetpConfigJetSystem(
  91. IN JET_INSTANCE *hinstance
  92. );
  93. SCESTATUS
  94. SceJetpGetValueFromVersion(
  95. IN PSCECONTEXT cxtProfile,
  96. IN LPSTR TableName,
  97. IN LPSTR ColumnName,
  98. OUT LPSTR Value OPTIONAL,
  99. IN DWORD ValueLen, // number of bytes
  100. OUT PDWORD pRetLen
  101. );
  102. SCESTATUS
  103. SceJetpAddGpo(
  104. IN PSCECONTEXT cxtProfile,
  105. IN JET_TABLEID TableID,
  106. IN JET_COLUMNID GpoIDColumnID,
  107. IN PCWSTR Name,
  108. OUT LONG *pGpoID
  109. );
  110. //
  111. // Code to handle profile
  112. //
  113. SCESTATUS
  114. SceJetOpenFile(
  115. IN LPSTR ProfileFileName,
  116. IN SCEJET_OPEN_TYPE Flags,
  117. IN DWORD dwTableOptions,
  118. OUT PSCECONTEXT *cxtProfile
  119. )
  120. /* ++
  121. Routine Description:
  122. This routine opens the profile (database) and outputs the context handle.
  123. The information returned in the context handle include the Jet session ID,
  124. Jet database ID, Jet table ID for SCP table, Jet column ID for column
  125. "Name" and "Value" in the SCP table, and optional information for SAP and
  126. SMP table.
  127. If the context handle passed in contains not NULL information, this routine
  128. will close all tables and the database in the context (use the same session).
  129. The context handle must be freed by LocalFree after its use.
  130. A new jet session is created when the context handle is created.
  131. Arguments:
  132. ProfileFileName - ASCII name of a database (profile)
  133. Flags - flags to open the database
  134. cxtProfile - the context handle (See SCECONTEXT structure)
  135. Return value:
  136. SCESTATUS_SUCCESS
  137. SCESTATUS_NOT_ENOUGH_RESOURCE
  138. SCESTATUS_PROFILE_NOT_FOUND
  139. SCESTATUS_ACCESS_DENIED
  140. SCESTATUS_BAD_FORMAT
  141. SCESTATUS_INVALID_PARAMETER
  142. SCESTATUS_OTHER_ERROR
  143. -- */
  144. {
  145. JET_ERR JetErr;
  146. SCESTATUS rc;
  147. BOOL FreeContext=FALSE;
  148. JET_GRBIT JetDbFlag;
  149. DWORD dwScpTable=0;
  150. if ( ProfileFileName == NULL || cxtProfile == NULL ) {
  151. return(SCESTATUS_INVALID_PARAMETER);
  152. }
  153. if ( *cxtProfile && ScepIsValidContext(*cxtProfile) ) {
  154. __try {
  155. //
  156. // Close previous opened database
  157. //
  158. rc = SceJetCloseFile(
  159. *cxtProfile,
  160. FALSE,
  161. FALSE
  162. );
  163. } __except (EXCEPTION_EXECUTE_HANDLER) {
  164. //
  165. // this is a invalid pointer
  166. //
  167. *cxtProfile = NULL;
  168. }
  169. }
  170. if ( *cxtProfile == NULL ) {
  171. //
  172. // no session
  173. //
  174. *cxtProfile = (PSCECONTEXT)LocalAlloc( LMEM_ZEROINIT, sizeof(SCECONTEXT));
  175. if ( *cxtProfile == NULL ) {
  176. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  177. }
  178. (*cxtProfile)->Type = 0xFFFFFF02L;
  179. (*cxtProfile)->JetSessionID = JET_sesidNil;
  180. (*cxtProfile)->JetDbID = JET_dbidNil;
  181. (*cxtProfile)->OpenFlag = SCEJET_OPEN_READ_WRITE;
  182. (*cxtProfile)->JetScpID = JET_tableidNil;
  183. (*cxtProfile)->JetSapID = JET_tableidNil;
  184. (*cxtProfile)->JetSmpID = JET_tableidNil;
  185. (*cxtProfile)->JetTblSecID = JET_tableidNil;
  186. FreeContext = TRUE;
  187. }
  188. //
  189. // Begin a session
  190. //
  191. if ( (*cxtProfile)->JetSessionID == JET_sesidNil ) {
  192. JetErr = JetBeginSession(
  193. JetInstance,
  194. &((*cxtProfile)->JetSessionID),
  195. NULL,
  196. NULL
  197. );
  198. rc = SceJetJetErrorToSceStatus(JetErr);
  199. if ( rc != SCESTATUS_SUCCESS )
  200. goto Done;
  201. }
  202. switch (Flags) {
  203. case SCEJET_OPEN_EXCLUSIVE:
  204. case SCEJET_OPEN_NOCHECK_VERSION:
  205. JetDbFlag = 0; // read & write
  206. // JetDbFlag = JET_bitDbExclusive;
  207. (*cxtProfile)->OpenFlag = SCEJET_OPEN_EXCLUSIVE;
  208. break;
  209. case SCEJET_OPEN_READ_ONLY:
  210. JetDbFlag = JET_bitDbReadOnly;
  211. (*cxtProfile)->OpenFlag = Flags;
  212. break;
  213. default:
  214. JetDbFlag = 0;
  215. (*cxtProfile)->OpenFlag = SCEJET_OPEN_READ_WRITE;
  216. break;
  217. }
  218. //
  219. // Attach database
  220. //
  221. JetErr = JetAttachDatabase(
  222. (*cxtProfile)->JetSessionID,
  223. ProfileFileName,
  224. JetDbFlag
  225. );
  226. #ifdef SCEJET_DBG
  227. printf("Attach database JetErr=%d\n", JetErr);
  228. #endif
  229. if ( JetErr == JET_wrnDatabaseAttached )
  230. JetErr = JET_errSuccess;
  231. rc = SceJetJetErrorToSceStatus(JetErr);
  232. if ( rc != SCESTATUS_SUCCESS )
  233. goto Done;
  234. //
  235. // Open database
  236. //
  237. JetErr = JetOpenDatabase(
  238. (*cxtProfile)->JetSessionID,
  239. ProfileFileName,
  240. NULL,
  241. &((*cxtProfile)->JetDbID),
  242. JetDbFlag //JET_bitDbExclusive
  243. );
  244. rc = SceJetJetErrorToSceStatus(JetErr);
  245. #ifdef SCEJET_DBG
  246. printf("Open database %s return code %d (%d) \n", ProfileFileName, rc, JetErr);
  247. #endif
  248. if ( rc != SCESTATUS_SUCCESS )
  249. goto Done;
  250. if ( Flags != SCEJET_OPEN_NOCHECK_VERSION ) {
  251. //
  252. // Check database format (for security manager, version#)
  253. //
  254. rc = SceJetCheckVersion( *cxtProfile, NULL );
  255. if ( rc != SCESTATUS_SUCCESS )
  256. goto Done;
  257. #ifdef SCEJET_DBG
  258. printf("Open: Version check OK\n");
  259. #endif
  260. }
  261. //
  262. // Open section table. must be there
  263. //
  264. rc = SceJetOpenTable(
  265. *cxtProfile,
  266. "SmTblSection",
  267. SCEJET_TABLE_SECTION,
  268. Flags,
  269. NULL
  270. );
  271. if ( rc != SCESTATUS_SUCCESS )
  272. goto Done;
  273. //
  274. // open smp table -- optional
  275. //
  276. rc = SceJetOpenTable(
  277. *cxtProfile,
  278. "SmTblSmp",
  279. SCEJET_TABLE_SMP,
  280. Flags,
  281. NULL
  282. );
  283. if ( rc != SCESTATUS_SUCCESS )
  284. goto Done;
  285. //
  286. // get the last used merge table (SCP) to open
  287. // shouldn't fail
  288. // 1 - SmTblScp 2 - SmTblScp2 0 - no policy merge
  289. //
  290. DWORD Actual;
  291. rc = SceJetpGetValueFromVersion(
  292. *cxtProfile,
  293. "SmTblVersion",
  294. "LastUsedMergeTable",
  295. (LPSTR)&dwScpTable,
  296. 4, // number of bytes
  297. &Actual
  298. );
  299. if ( (dwScpTable != SCEJET_MERGE_TABLE_1) &&
  300. (dwScpTable != SCEJET_MERGE_TABLE_2) ) {
  301. dwScpTable = SCEJET_LOCAL_TABLE;
  302. }
  303. rc = SCESTATUS_SUCCESS;
  304. (*cxtProfile)->Type &= 0xFFFFFF0FL;
  305. if ( dwTableOptions & SCE_TABLE_OPTION_MERGE_POLICY ) {
  306. //
  307. // in policy propagation
  308. //
  309. if ( ( dwScpTable == SCEJET_MERGE_TABLE_2 ) ) {
  310. //
  311. // the second table is already propped
  312. //
  313. rc = SceJetOpenTable(
  314. *cxtProfile,
  315. "SmTblScp",
  316. SCEJET_TABLE_SCP,
  317. Flags,
  318. NULL
  319. );
  320. (*cxtProfile)->Type |= SCEJET_MERGE_TABLE_1;
  321. } else {
  322. rc = SceJetOpenTable(
  323. *cxtProfile,
  324. "SmTblScp2",
  325. SCEJET_TABLE_SCP,
  326. Flags,
  327. NULL
  328. );
  329. (*cxtProfile)->Type |= SCEJET_MERGE_TABLE_2;
  330. }
  331. } else {
  332. switch ( dwScpTable ) {
  333. case SCEJET_MERGE_TABLE_2:
  334. //
  335. // the second table
  336. //
  337. rc = SceJetOpenTable(
  338. *cxtProfile,
  339. "SmTblScp2",
  340. SCEJET_TABLE_SCP,
  341. Flags,
  342. NULL
  343. );
  344. break;
  345. case SCEJET_MERGE_TABLE_1:
  346. rc = SceJetOpenTable(
  347. *cxtProfile,
  348. "SmTblScp",
  349. SCEJET_TABLE_SCP,
  350. Flags,
  351. NULL
  352. );
  353. break;
  354. default:
  355. //
  356. // open SMP table instead, because SCP table doesn't have information
  357. //
  358. (*cxtProfile)->JetScpID = (*cxtProfile)->JetSmpID;
  359. (*cxtProfile)->JetScpSectionID = (*cxtProfile)->JetSmpSectionID;
  360. (*cxtProfile)->JetScpNameID = (*cxtProfile)->JetSmpNameID;
  361. (*cxtProfile)->JetScpValueID = (*cxtProfile)->JetSmpValueID;
  362. (*cxtProfile)->JetScpGpoID = 0;
  363. break;
  364. }
  365. (*cxtProfile)->Type |= dwScpTable;
  366. }
  367. if ( rc != SCESTATUS_SUCCESS )
  368. goto Done;
  369. if ( dwTableOptions & SCE_TABLE_OPTION_TATTOO ) {
  370. rc = SceJetOpenTable(
  371. *cxtProfile,
  372. "SmTblTattoo",
  373. SCEJET_TABLE_TATTOO,
  374. Flags,
  375. NULL
  376. );
  377. } else {
  378. //
  379. // open sap table -- optional
  380. //
  381. rc = SceJetOpenTable(
  382. *cxtProfile,
  383. "SmTblSap",
  384. SCEJET_TABLE_SAP,
  385. Flags,
  386. NULL
  387. );
  388. }
  389. Done:
  390. if ( rc != SCESTATUS_SUCCESS ) {
  391. SceJetCloseFile(
  392. *cxtProfile,
  393. FALSE,
  394. FALSE
  395. );
  396. if ( FreeContext == TRUE ) {
  397. if ( (*cxtProfile)->JetSessionID != JET_sesidNil ) {
  398. JetEndSession(
  399. (*cxtProfile)->JetSessionID,
  400. JET_bitForceSessionClosed
  401. );
  402. }
  403. LocalFree(*cxtProfile);
  404. *cxtProfile = NULL;
  405. }
  406. }
  407. return(rc);
  408. }
  409. SCESTATUS
  410. SceJetCreateFile(
  411. IN LPSTR ProfileFileName,
  412. IN SCEJET_CREATE_TYPE Flags,
  413. IN DWORD dwTableOptions,
  414. OUT PSCECONTEXT *cxtProfile
  415. )
  416. /* ++
  417. Routine Description:
  418. This routine creates a database (profile) and outputs the context handle.
  419. See comments in SceJetOpenFile for information contained in the context.
  420. If the database name already exists in the system, there are 3 options:
  421. Flags = SCEJET_OVERWRITE_DUP - the existing database will be erased and
  422. recreated.
  423. Flags = SCEJET_OPEN_DUP - the existing database will be opened and
  424. format is checked
  425. Flags = SCEJET_OPEN_DUP_EXCLUSIVE - the existing database will be opened
  426. exclusively.
  427. Flags = SCEJET_RETURN_ON_DUP - a error code SCESTATUS_FILE_EXIST is returned.
  428. When creating the database, only SCP table is created initially. SAP and SMP
  429. tables will be created when analysis is performed.
  430. The context handle must be freed by LocalFree after its use.
  431. Arguments:
  432. ProfileFileName - ASCII name of a database to create.
  433. Flags - This flag is used when there is an duplicate database
  434. SCEJET_OVERWRITE_DUP
  435. SCEJET_OPEN_DUP
  436. SCEJET_OPEN_DUP_EXCLUSIVE
  437. SCEJET_RETURN_ON_DUP
  438. cxtProfile - The context handle
  439. Return value:
  440. SCESTATUS_SUCCESS
  441. SCESTATUS_NOT_ENOUGH_RESOURCE
  442. SCESTATUS_ACCESS_DENIED
  443. SCESTATUS_PROFILE_NOT_FOUND
  444. SCESTATUS_OBJECT_EXIST
  445. SCESTATUS_INVALID_PARAMETER
  446. SCESTATUS_CANT_DELETE
  447. SCESTATUS_OTHER_ERROR
  448. SCESTATUS from SceJetOpenFile
  449. -- */
  450. {
  451. JET_ERR JetErr;
  452. SCESTATUS rc=SCESTATUS_SUCCESS;
  453. BOOL FreeContext=FALSE;
  454. DWORD Len;
  455. FLOAT Version=(FLOAT)1.2;
  456. JET_TABLEID TableID;
  457. JET_COLUMNID ColumnID;
  458. if ( ProfileFileName == NULL || cxtProfile == NULL ) {
  459. return(SCESTATUS_INVALID_PARAMETER);
  460. }
  461. if ( *cxtProfile && ScepIsValidContext(*cxtProfile) ) {
  462. //
  463. // Close previous opened database
  464. //
  465. rc = SceJetCloseFile(
  466. *cxtProfile,
  467. FALSE,
  468. FALSE
  469. );
  470. } else {
  471. *cxtProfile = NULL;
  472. }
  473. if ( *cxtProfile == NULL ) {
  474. //
  475. // no session
  476. //
  477. *cxtProfile = (PSCECONTEXT)LocalAlloc( LMEM_ZEROINIT, sizeof(SCECONTEXT));
  478. if ( *cxtProfile == NULL ) {
  479. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  480. }
  481. (*cxtProfile)->Type = 0xFFFFFF02L;
  482. (*cxtProfile)->JetSessionID = JET_sesidNil;
  483. (*cxtProfile)->JetDbID = JET_dbidNil;
  484. (*cxtProfile)->OpenFlag = SCEJET_OPEN_READ_WRITE;
  485. (*cxtProfile)->JetScpID = JET_tableidNil;
  486. (*cxtProfile)->JetSapID = JET_tableidNil;
  487. (*cxtProfile)->JetSmpID = JET_tableidNil;
  488. (*cxtProfile)->JetTblSecID = JET_tableidNil;
  489. FreeContext = TRUE;
  490. }
  491. (*cxtProfile)->Type &= 0xFFFFFF0FL;
  492. //
  493. // Begin a session
  494. //
  495. if ( (*cxtProfile)->JetSessionID == JET_sesidNil ) {
  496. JetErr = JetBeginSession(
  497. JetInstance,
  498. &((*cxtProfile)->JetSessionID),
  499. NULL,
  500. NULL
  501. );
  502. rc = SceJetJetErrorToSceStatus(JetErr);
  503. if ( rc != SCESTATUS_SUCCESS )
  504. goto Done;
  505. }
  506. //
  507. // Create database
  508. //
  509. JetErr = JetCreateDatabase(
  510. (*cxtProfile)->JetSessionID,
  511. ProfileFileName,
  512. NULL,
  513. &((*cxtProfile)->JetDbID),
  514. JET_bitDbExclusive
  515. );
  516. if ( JET_errFileNotFound == JetErr ) {
  517. //
  518. // if no access to create a file in the path
  519. // ESENT returns this error. It's fixed in ESE98
  520. // we have to mask it to access denied error for now
  521. //
  522. JetErr = JET_errFileAccessDenied;
  523. }
  524. #ifdef SCEJET_DBG
  525. printf("Create database %s JetErr = %d\n", ProfileFileName, JetErr);
  526. #endif
  527. rc = SceJetJetErrorToSceStatus(JetErr);
  528. (*cxtProfile)->OpenFlag = SCEJET_OPEN_EXCLUSIVE;
  529. if ( rc == SCESTATUS_OBJECT_EXIST ) {
  530. switch ( Flags ) {
  531. case SCEJET_OVERWRITE_DUP:
  532. //
  533. // erase the database
  534. //
  535. JetDetachDatabase(
  536. (*cxtProfile)->JetSessionID,
  537. ProfileFileName
  538. );
  539. if ( !DeleteFileA(ProfileFileName) &&
  540. GetLastError() != ERROR_FILE_NOT_FOUND ) {
  541. ScepLogOutput3(1,GetLastError(), SCEDLL_ERROR_DELETE_DB );
  542. }
  543. //
  544. // if delete database failed, log the error but continue to
  545. // create the database. This call will fail with Jet error.
  546. //
  547. JetErr = JetCreateDatabase(
  548. (*cxtProfile)->JetSessionID,
  549. ProfileFileName,
  550. NULL,
  551. &((*cxtProfile)->JetDbID),
  552. JET_bitDbExclusive
  553. );
  554. if ( JET_errFileNotFound == JetErr ) {
  555. //
  556. // if no access to create a file in the path
  557. // ESENT returns this error. It's fixed in ESE98
  558. // we have to mask it to access denied error for now
  559. //
  560. JetErr = JET_errFileAccessDenied;
  561. }
  562. rc = SceJetJetErrorToSceStatus(JetErr);
  563. break;
  564. case SCEJET_OPEN_DUP:
  565. //
  566. // Open the database
  567. //
  568. rc = SceJetOpenFile(
  569. ProfileFileName,
  570. SCEJET_OPEN_READ_WRITE,
  571. dwTableOptions,
  572. cxtProfile
  573. );
  574. goto Done;
  575. break;
  576. case SCEJET_OPEN_DUP_EXCLUSIVE:
  577. //
  578. // Open the database
  579. //
  580. rc = SceJetOpenFile(
  581. ProfileFileName,
  582. SCEJET_OPEN_EXCLUSIVE,
  583. dwTableOptions,
  584. cxtProfile
  585. );
  586. goto Done;
  587. break;
  588. }
  589. }
  590. if ( rc != SCESTATUS_SUCCESS )
  591. goto Done;
  592. #ifdef SCEJET_DBG
  593. printf("Create/Open database\n");
  594. #endif
  595. //
  596. // create required tables - SmTblVersion
  597. //
  598. rc = SceJetCreateTable(
  599. *cxtProfile,
  600. "SmTblVersion",
  601. SCEJET_TABLE_VERSION,
  602. SCEJET_CREATE_IN_BUFFER,
  603. &TableID,
  604. &ColumnID
  605. );
  606. if ( rc != SCESTATUS_SUCCESS )
  607. goto Done;
  608. //
  609. // insert one record into the version table
  610. //
  611. JetErr = JetPrepareUpdate((*cxtProfile)->JetSessionID,
  612. TableID,
  613. JET_prepInsert
  614. );
  615. rc = SceJetJetErrorToSceStatus(JetErr);
  616. if ( rc == SCESTATUS_SUCCESS ) {
  617. //
  618. // set value "1.2" in "Version" column
  619. //
  620. JetErr = JetSetColumn(
  621. (*cxtProfile)->JetSessionID,
  622. TableID,
  623. ColumnID,
  624. (void *)&Version,
  625. 4,
  626. 0, //JET_bitSetOverwriteLV,
  627. NULL
  628. );
  629. rc = SceJetJetErrorToSceStatus(JetErr);
  630. if ( rc != SCESTATUS_SUCCESS ) {
  631. //
  632. // if setting fails, cancel the prepared record
  633. //
  634. JetPrepareUpdate( (*cxtProfile)->JetSessionID,
  635. TableID,
  636. JET_prepCancel
  637. );
  638. } else {
  639. //
  640. // Setting columns succeed. Update the record
  641. //
  642. JetErr = JetUpdate( (*cxtProfile)->JetSessionID,
  643. TableID,
  644. NULL,
  645. 0,
  646. &Len
  647. );
  648. rc = SceJetJetErrorToSceStatus(JetErr);
  649. }
  650. }
  651. if ( rc != SCESTATUS_SUCCESS )
  652. goto Done;
  653. #ifdef SCEJET_DBG
  654. printf("create version table\n");
  655. #endif
  656. //
  657. // create section table and insert pre-defined sections
  658. //
  659. rc = SceJetCreateTable(
  660. *cxtProfile,
  661. "SmTblSection",
  662. SCEJET_TABLE_SECTION,
  663. SCEJET_CREATE_IN_BUFFER,
  664. NULL,
  665. NULL
  666. );
  667. if ( rc != SCESTATUS_SUCCESS )
  668. goto Done;
  669. #ifdef SCEJET_DBG
  670. printf("create section table\n");
  671. #endif
  672. rc = SceJetpAddAllSections(
  673. *cxtProfile
  674. );
  675. if ( rc != SCESTATUS_SUCCESS )
  676. goto Done;
  677. #ifdef SCEJET_DBG
  678. printf("add sections\n");
  679. #endif
  680. //
  681. // create scp table
  682. //
  683. rc = SceJetCreateTable(
  684. *cxtProfile,
  685. "SmTblScp",
  686. SCEJET_TABLE_SCP,
  687. SCEJET_CREATE_IN_BUFFER,
  688. NULL,
  689. NULL
  690. );
  691. #ifdef SCEJET_DBG
  692. printf("Create table scp %d\n", rc);
  693. #endif
  694. if ( rc != SCESTATUS_SUCCESS )
  695. goto Done;
  696. if ( dwTableOptions & SCE_TABLE_OPTION_MERGE_POLICY ) {
  697. (*cxtProfile)->Type |= SCEJET_MERGE_TABLE_1;
  698. } else {
  699. (*cxtProfile)->Type |= SCEJET_LOCAL_TABLE;
  700. }
  701. //
  702. // create scp table
  703. //
  704. rc = SceJetCreateTable(
  705. *cxtProfile,
  706. "SmTblSmp",
  707. SCEJET_TABLE_SMP,
  708. SCEJET_CREATE_IN_BUFFER,
  709. NULL,
  710. NULL
  711. );
  712. #ifdef SCEJET_DBG
  713. printf("Create table smp %d\n", rc);
  714. #endif
  715. if ( rc != SCESTATUS_SUCCESS )
  716. goto Done;
  717. rc = SceJetCreateTable(
  718. *cxtProfile,
  719. "SmTblScp2",
  720. SCEJET_TABLE_SCP,
  721. SCEJET_CREATE_NO_TABLEID,
  722. NULL,
  723. NULL
  724. );
  725. if ( rc != SCESTATUS_SUCCESS )
  726. goto Done;
  727. rc = SceJetCreateTable(
  728. *cxtProfile,
  729. "SmTblGpo",
  730. SCEJET_TABLE_GPO,
  731. SCEJET_CREATE_NO_TABLEID,
  732. NULL,
  733. NULL
  734. );
  735. if ( rc != SCESTATUS_SUCCESS )
  736. goto Done;
  737. if ( dwTableOptions & SCE_TABLE_OPTION_TATTOO ) {
  738. rc = SceJetCreateTable(
  739. *cxtProfile,
  740. "SmTblTattoo",
  741. SCEJET_TABLE_TATTOO,
  742. SCEJET_CREATE_IN_BUFFER,
  743. NULL,
  744. NULL
  745. );
  746. }
  747. Done:
  748. //
  749. // clearn up if error out
  750. //
  751. if ( rc != SCESTATUS_SUCCESS ) {
  752. SceJetCloseFile(
  753. *cxtProfile,
  754. FALSE,
  755. FALSE
  756. );
  757. if ( FreeContext == TRUE ) {
  758. if ( (*cxtProfile)->JetSessionID != JET_sesidNil ) {
  759. JetEndSession(
  760. (*cxtProfile)->JetSessionID,
  761. JET_bitForceSessionClosed
  762. );
  763. }
  764. LocalFree(*cxtProfile);
  765. *cxtProfile = NULL;
  766. }
  767. }
  768. return(rc);
  769. }
  770. SCESTATUS
  771. SceJetCloseFile(
  772. IN PSCECONTEXT hProfile,
  773. IN BOOL TermSession,
  774. IN BOOL Terminate
  775. )
  776. /* ++
  777. Routine Description:
  778. This routine closes a context handle, which closes all tables opened in
  779. the database and then closes the database.
  780. Terminate parameter is ignored and Jet engine is not stoppped when this parameter
  781. is set to TRUE, because there might be other clients using Jet and Jet writer is
  782. dependent on it.
  783. Arguments:
  784. hProfile - The context handle
  785. Terminate - TRUE = Terminate the Jet session and engine.
  786. Return value:
  787. SCESTATUS_SUCCESS
  788. -- */
  789. {
  790. JET_ERR JetErr;
  791. if ( hProfile == NULL )
  792. goto Terminate;
  793. CHAR szDbName[1025];
  794. //
  795. // Close SCP table if it is opened
  796. //
  797. if ( (hProfile->JetScpID != JET_tableidNil) ) {
  798. if ( hProfile->JetScpID != hProfile->JetSmpID ) {
  799. JetErr = JetCloseTable(
  800. hProfile->JetSessionID,
  801. hProfile->JetScpID
  802. );
  803. }
  804. hProfile->JetScpID = JET_tableidNil;
  805. }
  806. //
  807. // Close SAP table if it is opened
  808. //
  809. if ( hProfile->JetSapID != JET_tableidNil ) {
  810. JetErr = JetCloseTable(
  811. hProfile->JetSessionID,
  812. hProfile->JetSapID
  813. );
  814. hProfile->JetSapID = JET_tableidNil;
  815. }
  816. //
  817. // Close SMP table if it is opened
  818. //
  819. if ( hProfile->JetSmpID != JET_tableidNil ) {
  820. JetErr = JetCloseTable(
  821. hProfile->JetSessionID,
  822. hProfile->JetSmpID
  823. );
  824. hProfile->JetSmpID = JET_tableidNil;
  825. }
  826. //
  827. // get database name
  828. // do not care if there is error
  829. //
  830. szDbName[0] = '\0';
  831. szDbName[1024] = '\0';
  832. if ( hProfile->JetDbID != JET_dbidNil ) {
  833. JetGetDatabaseInfo(hProfile->JetSessionID,
  834. hProfile->JetDbID,
  835. (void *)szDbName,
  836. 1024,
  837. JET_DbInfoFilename
  838. );
  839. //
  840. // Close the database
  841. //
  842. JetErr = JetCloseDatabase(
  843. hProfile->JetSessionID,
  844. hProfile->JetDbID,
  845. 0
  846. );
  847. hProfile->JetDbID = JET_dbidNil;
  848. //
  849. // should detach the database if the database name is not NULL
  850. // the database is always attached when it's to open
  851. // do not care error
  852. //
  853. if ( szDbName[0] != '\0' ) {
  854. JetDetachDatabase(hProfile->JetSessionID, szDbName);
  855. }
  856. }
  857. if ( TermSession || Terminate ) {
  858. if ( hProfile->JetSessionID != JET_sesidNil ) {
  859. JetEndSession(
  860. hProfile->JetSessionID,
  861. JET_bitForceSessionClosed
  862. );
  863. hProfile->JetSessionID = JET_sesidNil;
  864. }
  865. hProfile->Type = 0;
  866. LocalFree(hProfile);
  867. }
  868. Terminate:
  869. /*
  870. if ( Terminate ) {
  871. JetTerm(JetInstance);
  872. JetInstance = 0;
  873. JetInited = FALSE;
  874. }
  875. */
  876. return(SCESTATUS_SUCCESS);
  877. }
  878. //
  879. // Code to handle sections
  880. //
  881. SCESTATUS
  882. SceJetOpenSection(
  883. IN PSCECONTEXT hProfile,
  884. IN DOUBLE SectionID,
  885. IN SCEJET_TABLE_TYPE tblType,
  886. OUT PSCESECTION *hSection
  887. )
  888. /* ++
  889. Routine Description:
  890. This routine saves table and section information in the section context
  891. handle for other section API's use. SCP, SAP, and SMP tables have the
  892. same section names. The table type indicates which table this section is
  893. in.
  894. The section context handle must be freed by LocalFree after its use.
  895. Arguments:
  896. hProfile - The profile context handle
  897. SectionID - ID of the section to open
  898. tblType - The type of the table for this section
  899. SCEJET_TABLE_SCP
  900. SCEJET_TABLE_SAP
  901. SCEJET_TABLE_SMP
  902. hSection - The seciton context handle
  903. Return Value:
  904. SCESTATUS_SUCCESS
  905. SCESTATUS_INVALID_PARAMETER
  906. SCESTATUS_NOT_ENOUGH_RESOURCE
  907. -- */
  908. {
  909. if ( hProfile == NULL ||
  910. hSection == NULL ||
  911. SectionID == (DOUBLE)0 ||
  912. (tblType != SCEJET_TABLE_SCP &&
  913. tblType != SCEJET_TABLE_SAP &&
  914. tblType != SCEJET_TABLE_SMP &&
  915. tblType != SCEJET_TABLE_TATTOO) )
  916. return(SCESTATUS_INVALID_PARAMETER);
  917. if ( hProfile->JetSessionID == JET_sesidNil ||
  918. hProfile->JetDbID == JET_dbidNil ||
  919. (tblType == SCEJET_TABLE_SCP && hProfile->JetScpID == JET_tableidNil ) ||
  920. (tblType == SCEJET_TABLE_SMP && hProfile->JetSmpID == JET_tableidNil ) ||
  921. (tblType == SCEJET_TABLE_SAP && hProfile->JetSapID == JET_tableidNil ) ||
  922. (tblType == SCEJET_TABLE_TATTOO && hProfile->JetSapID == JET_tableidNil ) )
  923. return(SCESTATUS_BAD_FORMAT);
  924. if ( *hSection == NULL ) {
  925. //
  926. // Allocate memory
  927. //
  928. *hSection = (PSCESECTION)LocalAlloc( (UINT)0, sizeof(SCESECTION));
  929. if ( *hSection == NULL ) {
  930. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  931. }
  932. }
  933. (*hSection)->SectionID = SectionID;
  934. //
  935. // assign other info to the section context
  936. //
  937. (*hSection)->JetSessionID = hProfile->JetSessionID;
  938. (*hSection)->JetDbID = hProfile->JetDbID;
  939. switch (tblType) {
  940. case SCEJET_TABLE_SCP:
  941. (*hSection)->JetTableID = hProfile->JetScpID;
  942. (*hSection)->JetColumnSectionID = hProfile->JetScpSectionID;
  943. (*hSection)->JetColumnNameID = hProfile->JetScpNameID;
  944. (*hSection)->JetColumnValueID = hProfile->JetScpValueID;
  945. (*hSection)->JetColumnGpoID = hProfile->JetScpGpoID;
  946. break;
  947. case SCEJET_TABLE_SAP:
  948. case SCEJET_TABLE_TATTOO:
  949. (*hSection)->JetTableID = hProfile->JetSapID;
  950. (*hSection)->JetColumnSectionID = hProfile->JetSapSectionID;
  951. (*hSection)->JetColumnNameID = hProfile->JetSapNameID;
  952. (*hSection)->JetColumnValueID = hProfile->JetSapValueID;
  953. (*hSection)->JetColumnGpoID = 0;
  954. break;
  955. default:
  956. (*hSection)->JetTableID = hProfile->JetSmpID;
  957. (*hSection)->JetColumnSectionID = hProfile->JetSmpSectionID;
  958. (*hSection)->JetColumnNameID = hProfile->JetSmpNameID;
  959. (*hSection)->JetColumnValueID = hProfile->JetSmpValueID;
  960. (*hSection)->JetColumnGpoID = 0;
  961. break;
  962. }
  963. return(SCESTATUS_SUCCESS);
  964. }
  965. SCESTATUS
  966. SceJetGetLineCount(
  967. IN PSCESECTION hSection,
  968. IN PWSTR LinePrefix OPTIONAL,
  969. IN BOOL bExactCase,
  970. OUT DWORD *Count
  971. )
  972. /* ++
  973. Fucntion Description:
  974. This routine counts the number of lines matching the LinePrefix (Key)
  975. in the section. If LinePrefix is NULL, all lines is counted.
  976. Arguments:
  977. hSection - The context handle for the section.
  978. LinePrefix - The whole or partial key to match. If NULL, all lines in the
  979. section is counted.
  980. Count - The output count.
  981. Return Value:
  982. SCESTATUS_SUCCESS
  983. SCESTATUS_INVALID_PARAMETER
  984. SCESTATUS_OTHER_ERROR
  985. -- */
  986. {
  987. SCESTATUS rc;
  988. JET_ERR JetErr;
  989. DWORD Len;
  990. INT Result=0;
  991. SCEJET_SEEK_FLAG SeekFlag;
  992. if ( hSection == NULL || Count == NULL ) {
  993. return(SCESTATUS_INVALID_PARAMETER);
  994. }
  995. //
  996. // initialize
  997. //
  998. *Count = 0;
  999. if ( LinePrefix == NULL ) {
  1000. Len = 0;
  1001. SeekFlag = SCEJET_SEEK_GE;
  1002. } else {
  1003. Len = wcslen(LinePrefix)*sizeof(WCHAR);
  1004. if ( bExactCase )
  1005. SeekFlag = SCEJET_SEEK_GE;
  1006. else
  1007. SeekFlag = SCEJET_SEEK_GE_NO_CASE;
  1008. }
  1009. //
  1010. // seek the first occurance
  1011. //
  1012. rc = SceJetSeek(
  1013. hSection,
  1014. LinePrefix,
  1015. Len,
  1016. SeekFlag
  1017. );
  1018. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  1019. // no matching record is found
  1020. return(SCESTATUS_SUCCESS);
  1021. }
  1022. if ( rc == SCESTATUS_SUCCESS ) {
  1023. //
  1024. // Find the record or the next record
  1025. // Define the upper index range
  1026. //
  1027. if ( Len <= 247 ) {
  1028. JetErr = SceJetpBuildUpperLimit(
  1029. hSection,
  1030. LinePrefix,
  1031. Len,
  1032. bExactCase
  1033. );
  1034. rc = SceJetJetErrorToSceStatus(JetErr);
  1035. if ( rc != SCESTATUS_SUCCESS )
  1036. return(rc);
  1037. //
  1038. // count from the current position to the end of the range
  1039. //
  1040. JetErr = JetIndexRecordCount(
  1041. hSection->JetSessionID,
  1042. hSection->JetTableID,
  1043. (unsigned long *)Count,
  1044. (unsigned long)0xFFFFFFFF // maximal count
  1045. );
  1046. rc = SceJetJetErrorToSceStatus(JetErr);
  1047. //
  1048. // reset the index range. don't care the error code returned
  1049. //
  1050. JetErr = JetSetIndexRange(
  1051. hSection->JetSessionID,
  1052. hSection->JetTableID,
  1053. JET_bitRangeRemove
  1054. );
  1055. } else {
  1056. //
  1057. // Prefix is longer than 247. The index built does not contan all info
  1058. // loop through each record to count
  1059. //
  1060. do {
  1061. // current record is the same.
  1062. *Count = *Count + 1;
  1063. //
  1064. // move to next record
  1065. //
  1066. JetErr = JetMove(hSection->JetSessionID,
  1067. hSection->JetTableID,
  1068. JET_MoveNext,
  1069. 0
  1070. );
  1071. rc = SceJetJetErrorToSceStatus(JetErr);
  1072. if ( rc == SCESTATUS_SUCCESS ) {
  1073. // check the record
  1074. JetErr = SceJetpCompareLine(
  1075. hSection,
  1076. JET_bitSeekGE,
  1077. LinePrefix,
  1078. Len,
  1079. &Result,
  1080. NULL
  1081. );
  1082. rc = SceJetJetErrorToSceStatus(JetErr);
  1083. }
  1084. } while ( rc == SCESTATUS_SUCCESS && Result == 0 );
  1085. }
  1086. if ( rc == SCESTATUS_RECORD_NOT_FOUND )
  1087. rc = SCESTATUS_SUCCESS;
  1088. }
  1089. return(rc);
  1090. }
  1091. SCESTATUS
  1092. SceJetDelete(
  1093. IN PSCESECTION hSection,
  1094. IN PWSTR LinePrefix,
  1095. IN BOOL bObjectFolder,
  1096. IN SCEJET_DELETE_TYPE Flags
  1097. )
  1098. /* ++
  1099. Fucntion Description:
  1100. This routine deletes the current record, prefix records, or the whole
  1101. section, depending on the Flags.
  1102. Arguments:
  1103. hSection - The context handle of the section
  1104. LinePrefix - The prefix to start with for the deleted lines. This value
  1105. is only used when Flags is set to SCEJET_DELETE_PARTIAL
  1106. Flags - Options
  1107. SCEJET_DELETE_SECTION
  1108. SCEJET_DELETE_LINE
  1109. SCEJET_DELETE_PARTIAL
  1110. Return Value:
  1111. SCESTATUS_SUCCESS
  1112. SCESTATUS_ACCESS_DEINED
  1113. SCESTATUS_RECORD_NOT_FOUND
  1114. SCESTATUS_OTHER_ERROR
  1115. -- */
  1116. {
  1117. JET_ERR JetErr;
  1118. SCESTATUS rc;
  1119. INT Result = 0;
  1120. PWSTR TempPrefix=NULL;
  1121. DWORD Len;
  1122. SCEJET_SEEK_FLAG SeekFlag;
  1123. PWSTR NewPrefix=NULL;
  1124. DOUBLE SectionID;
  1125. DWORD Actual;
  1126. if ( hSection == NULL ) {
  1127. return(SCESTATUS_INVALID_PARAMETER);
  1128. }
  1129. if ( Flags == SCEJET_DELETE_PARTIAL ||
  1130. Flags == SCEJET_DELETE_PARTIAL_NO_CASE ) {
  1131. if ( LinePrefix == NULL )
  1132. return(SCESTATUS_INVALID_PARAMETER);
  1133. Len = wcslen(LinePrefix);
  1134. //
  1135. // delete this node exact match first
  1136. //
  1137. if ( Flags == SCEJET_DELETE_PARTIAL )
  1138. SeekFlag = SCEJET_SEEK_EQ;
  1139. else
  1140. SeekFlag = SCEJET_SEEK_EQ_NO_CASE;
  1141. rc = SceJetSeek(hSection,
  1142. LinePrefix,
  1143. Len*sizeof(WCHAR),
  1144. SeekFlag
  1145. );
  1146. if ( rc == SCESTATUS_SUCCESS ) {
  1147. JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
  1148. rc = SceJetJetErrorToSceStatus(JetErr);
  1149. }
  1150. if ( SCESTATUS_RECORD_NOT_FOUND == rc ) {
  1151. rc = SCESTATUS_SUCCESS;
  1152. }
  1153. if ( rc == SCESTATUS_SUCCESS ) {
  1154. if ( bObjectFolder &&
  1155. LinePrefix[Len-1] != L'\\' ) {
  1156. Len++;
  1157. NewPrefix = (PWSTR)ScepAlloc(0, (Len+1)*sizeof(WCHAR));
  1158. if ( NewPrefix == NULL ) {
  1159. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  1160. }
  1161. wcscpy(NewPrefix, LinePrefix);
  1162. wcscat(NewPrefix, L"\\");
  1163. }
  1164. } else {
  1165. return(rc);
  1166. }
  1167. Len = Len*sizeof(WCHAR);
  1168. }
  1169. if ( Flags == SCEJET_DELETE_LINE ||
  1170. Flags == SCEJET_DELETE_LINE_NO_CASE ) {
  1171. if ( LinePrefix == NULL ) {
  1172. //
  1173. // delete current line
  1174. // check the current's sectionID before deleting
  1175. //
  1176. rc = SceJetJetErrorToSceStatus(JetRetrieveColumn(
  1177. hSection->JetSessionID,
  1178. hSection->JetTableID,
  1179. hSection->JetColumnSectionID,
  1180. (void *)&SectionID,
  1181. 8,
  1182. &Actual,
  1183. 0,
  1184. NULL
  1185. ));
  1186. if (rc == SCESTATUS_SUCCESS && hSection->SectionID != SectionID)
  1187. rc = SCESTATUS_RECORD_NOT_FOUND;
  1188. if (rc == SCESTATUS_SUCCESS) {
  1189. JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
  1190. rc = SceJetJetErrorToSceStatus(JetErr);
  1191. }
  1192. } else {
  1193. if ( Flags == SCEJET_DELETE_LINE )
  1194. SeekFlag = SCEJET_SEEK_EQ;
  1195. else
  1196. SeekFlag = SCEJET_SEEK_EQ_NO_CASE;
  1197. rc = SceJetSeek(hSection,
  1198. LinePrefix,
  1199. wcslen(LinePrefix)*sizeof(WCHAR),
  1200. SeekFlag
  1201. );
  1202. if ( rc == SCESTATUS_SUCCESS ) {
  1203. JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
  1204. rc = SceJetJetErrorToSceStatus(JetErr);
  1205. }
  1206. }
  1207. return(rc);
  1208. }
  1209. if ( Flags == SCEJET_DELETE_SECTION ||
  1210. Flags == SCEJET_DELETE_PARTIAL ||
  1211. Flags == SCEJET_DELETE_PARTIAL_NO_CASE ) {
  1212. if ( Flags == SCEJET_DELETE_SECTION ) {
  1213. //
  1214. // delete the whole section
  1215. // seek the first line of the section
  1216. //
  1217. TempPrefix = NULL;
  1218. Len = 0;
  1219. SeekFlag = SCEJET_SEEK_GE;
  1220. } else {
  1221. //
  1222. // delete all lines begin with the prefix
  1223. // seek the first line of the prefix
  1224. //
  1225. if ( NewPrefix ) {
  1226. TempPrefix = NewPrefix;
  1227. } else {
  1228. TempPrefix = LinePrefix;
  1229. }
  1230. if ( Flags == SCEJET_DELETE_PARTIAL_NO_CASE )
  1231. SeekFlag = SCEJET_SEEK_GE_NO_CASE;
  1232. else
  1233. SeekFlag = SCEJET_SEEK_GE;
  1234. }
  1235. rc = SceJetSeek(hSection, TempPrefix, Len, SeekFlag);
  1236. if ( rc != SCESTATUS_SUCCESS ) {
  1237. if ( NewPrefix ) {
  1238. ScepFree(NewPrefix);
  1239. }
  1240. return(rc);
  1241. }
  1242. do {
  1243. //
  1244. // delete current line
  1245. //
  1246. JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
  1247. rc = SceJetJetErrorToSceStatus(JetErr);
  1248. if ( rc != SCESTATUS_SUCCESS )
  1249. break;
  1250. //
  1251. // move cursor to next line
  1252. //
  1253. JetErr = JetMove(hSection->JetSessionID,
  1254. hSection->JetTableID,
  1255. JET_MoveNext,
  1256. 0
  1257. );
  1258. if ( JetErr == JET_errSuccess ) {
  1259. //
  1260. // compare section ID
  1261. //
  1262. JetErr = SceJetpCompareLine(
  1263. hSection,
  1264. JET_bitSeekGE,
  1265. TempPrefix,
  1266. Len,
  1267. &Result,
  1268. NULL
  1269. );
  1270. if ( JetErr == JET_errSuccess && Result != 0 )
  1271. JetErr = JET_errRecordNotFound;
  1272. }
  1273. if ( JetErr == JET_errRecordDeleted ) {
  1274. //
  1275. // skip the deleted record
  1276. //
  1277. JetErr = JET_errSuccess;
  1278. Result = 0;
  1279. }
  1280. rc = SceJetJetErrorToSceStatus(JetErr);
  1281. } while ( rc == SCESTATUS_SUCCESS && Result == 0 );
  1282. if ( rc == SCESTATUS_RECORD_NOT_FOUND )
  1283. rc = SCESTATUS_SUCCESS;
  1284. if ( NewPrefix ) {
  1285. ScepFree(NewPrefix);
  1286. }
  1287. return(rc);
  1288. }
  1289. return(SCESTATUS_SUCCESS);
  1290. }
  1291. SCESTATUS
  1292. SceJetDeleteAll(
  1293. IN PSCECONTEXT cxtProfile,
  1294. IN LPSTR TblName OPTIONAL,
  1295. IN SCEJET_TABLE_TYPE TblType
  1296. )
  1297. /* ++
  1298. Fucntion Description:
  1299. This routine deletes everything in the table (specified by name or by type)
  1300. Arguments:
  1301. cxtProfile - The context handle of the database
  1302. TblName - optional table name to delete (if not to use the table id in context)
  1303. TblType - specify the table type to use the table id in context, ignored
  1304. if TblName is specified.
  1305. Return Value:
  1306. -- */
  1307. {
  1308. JET_ERR JetErr;
  1309. SCESTATUS rc;
  1310. JET_TABLEID tmpTblID;
  1311. if ( cxtProfile == NULL ) {
  1312. return(SCESTATUS_INVALID_PARAMETER);
  1313. }
  1314. if ( TblName ) {
  1315. JetErr = JetOpenTable(
  1316. cxtProfile->JetSessionID,
  1317. cxtProfile->JetDbID,
  1318. TblName,
  1319. NULL,
  1320. 0,
  1321. 0,
  1322. &tmpTblID
  1323. );
  1324. if ( JET_errSuccess != JetErr ) {
  1325. return(SceJetJetErrorToSceStatus(JetErr));
  1326. }
  1327. } else {
  1328. switch ( TblType ) {
  1329. case SCEJET_TABLE_SCP:
  1330. tmpTblID = cxtProfile->JetScpID;
  1331. break;
  1332. case SCEJET_TABLE_SMP:
  1333. tmpTblID = cxtProfile->JetSmpID;
  1334. break;
  1335. case SCEJET_TABLE_SAP:
  1336. case SCEJET_TABLE_TATTOO:
  1337. tmpTblID = cxtProfile->JetSapID;
  1338. break;
  1339. case SCEJET_TABLE_SECTION:
  1340. tmpTblID = cxtProfile->JetTblSecID;
  1341. break;
  1342. default:
  1343. return(SCESTATUS_INVALID_PARAMETER);
  1344. }
  1345. }
  1346. //
  1347. // move cursor to next line
  1348. //
  1349. JetErr = JetMove(cxtProfile->JetSessionID,
  1350. tmpTblID,
  1351. JET_MoveFirst,
  1352. 0
  1353. );
  1354. while ( JET_errSuccess == JetErr ) {
  1355. //
  1356. // delete current line
  1357. //
  1358. JetErr = JetDelete(cxtProfile->JetSessionID, tmpTblID);
  1359. //
  1360. // move cursor to next line
  1361. //
  1362. JetErr = JetMove(cxtProfile->JetSessionID,
  1363. tmpTblID,
  1364. JET_MoveNext,
  1365. 0
  1366. );
  1367. }
  1368. rc = SceJetJetErrorToSceStatus(JetErr);
  1369. if ( rc == SCESTATUS_RECORD_NOT_FOUND )
  1370. rc = SCESTATUS_SUCCESS;
  1371. if ( TblName ) {
  1372. JetCloseTable(cxtProfile->JetSessionID, tmpTblID);
  1373. }
  1374. return(rc);
  1375. }
  1376. SCESTATUS
  1377. SceJetCloseSection(
  1378. IN PSCESECTION *hSection,
  1379. IN BOOL DestroySection
  1380. )
  1381. /* ++
  1382. Fucntion Description:
  1383. Closes a section context handle.
  1384. Arguments:
  1385. hSection - The section context handle to close
  1386. Return Value:
  1387. SCE_SUCCESS
  1388. -- */
  1389. {
  1390. if ( hSection == NULL ) {
  1391. return(SCESTATUS_INVALID_PARAMETER);
  1392. }
  1393. if ( *hSection != NULL ) {
  1394. (*hSection)->JetColumnSectionID = 0;
  1395. (*hSection)->JetColumnNameID = 0;
  1396. (*hSection)->JetColumnValueID = 0;
  1397. (*hSection)->SectionID = (DOUBLE)0;
  1398. if ( DestroySection ) {
  1399. ScepFree(*hSection);
  1400. *hSection = NULL;
  1401. }
  1402. }
  1403. return(SCESTATUS_SUCCESS);
  1404. }
  1405. //
  1406. // Code to handle line
  1407. //
  1408. SCESTATUS
  1409. SceJetGetValue(
  1410. IN PSCESECTION hSection,
  1411. IN SCEJET_FIND_TYPE Flags,
  1412. IN PWSTR LinePrefix OPTIONAL,
  1413. IN PWSTR ActualName OPTIONAL,
  1414. IN DWORD NameBufLen,
  1415. OUT DWORD *RetNameLen OPTIONAL,
  1416. IN PWSTR Value OPTIONAL,
  1417. IN DWORD ValueBufLen,
  1418. OUT DWORD *RetValueLen OPTIONAL
  1419. )
  1420. /* ++
  1421. Fucntion Description:
  1422. This routine retrieves a line from the opened section or close the
  1423. previous search context. When Flag is SCEJET_EXACT_MATCH, this routine
  1424. returns the exact matched line for LinePrefix (LinePrefix can't be NULL).
  1425. If this routine is used to get multiple lines, a SCEJET_PREFIX_MATCH
  1426. must be used for the Flags when the first time it is called. If LinePrefix
  1427. is NULL, the first line in the section is returned; otherwise, the first
  1428. line matching the prefix is returned. When continous call is made for the
  1429. same prefix, use SCEJET_NEXT_LINE for the Flags. LinePrefix is not used
  1430. for continous calls. When finish with the continuous calls, a
  1431. SCEJET_CLOSE_VALUE must be used to close the search handle context.
  1432. ActualName and Value contains the actual name and value stored in the
  1433. database for the current line. If these two buffers are not big enough,
  1434. an error will return SCE_BUFFER_TOO_SMALL.
  1435. Passing NULL for ActualName or Value will return the required length for
  1436. that buffer if the RetLength buffer is not NULL.
  1437. Arguments:
  1438. hSection - The context handle of the section
  1439. LinePrefix - The prefix for the line to start with. This is used only
  1440. when Flags is set to SCEJET_PREFIX_MATCH
  1441. Flags - Options for the operation
  1442. SCEJET_EXACT_MATCH
  1443. SCEJET_PREFIX_MATCH
  1444. SCEJET_NEXT_LINE
  1445. SCEJET_CLOSE_VALUE
  1446. SCEJET_CURRENT -- get current record's value
  1447. ActualName - The buffer for column "Name"
  1448. NameBufLen - The buffer length of ActualName
  1449. RetNameLen - the required buffer length for "Name" column
  1450. Value - The buffer for column "Value"
  1451. ValueBufLen - The buffer length of Value
  1452. RetValueLen - The required buffer length for "Value" column
  1453. Return Value:
  1454. SCESTATUS_SUCCESS if success
  1455. SCESTATUS_RECORD_NOT_FOUND if no more match
  1456. other errors:
  1457. SCESTATUS_INVALID_PARAMETER
  1458. SCESTATUS_BUFFER_TOO_SMALL
  1459. SCESTATUS_OTHER_ERROR
  1460. -- */
  1461. {
  1462. JET_ERR JetErr;
  1463. SCESTATUS rc=SCESTATUS_SUCCESS;
  1464. SCESTATUS rc1;
  1465. DWORD Len=0;
  1466. JET_RETINFO RetInfo;
  1467. WCHAR Buffer[128];
  1468. PVOID pTemp=NULL;
  1469. INT Result=0;
  1470. SCEJET_SEEK_FLAG SeekFlag=SCEJET_SEEK_GT;
  1471. if ( hSection == NULL )
  1472. return(SCESTATUS_INVALID_PARAMETER);
  1473. if ( Flags == SCEJET_CLOSE_VALUE ) {
  1474. //
  1475. // close the index range
  1476. //
  1477. if ( FindContext.Length > 0 ) {
  1478. memset(FindContext.Prefix, '\0', FindContext.Length);
  1479. FindContext.Length = 0;
  1480. }
  1481. JetErr = JetSetIndexRange(
  1482. hSection->JetSessionID,
  1483. hSection->JetTableID,
  1484. JET_bitRangeRemove
  1485. );
  1486. if ( JetErr != JET_errSuccess &&
  1487. JetErr != JET_errKeyNotMade &&
  1488. JetErr != JET_errNoCurrentRecord ) {
  1489. return(SceJetJetErrorToSceStatus(JetErr));
  1490. }
  1491. return(SCESTATUS_SUCCESS);
  1492. }
  1493. //
  1494. // when name/value is requested (not NULL), the return length buffer
  1495. // cannot be NULL.
  1496. // both return length buffer cannot be NULL at the same time
  1497. //
  1498. if ( (ActualName != NULL && RetNameLen == NULL) ||
  1499. (Value != NULL && RetValueLen == NULL) ) {
  1500. return(SCESTATUS_INVALID_PARAMETER);
  1501. }
  1502. switch ( Flags ) {
  1503. case SCEJET_EXACT_MATCH:
  1504. case SCEJET_EXACT_MATCH_NO_CASE:
  1505. if ( LinePrefix == NULL )
  1506. return(SCESTATUS_INVALID_PARAMETER);
  1507. Len = wcslen(LinePrefix)*sizeof(WCHAR);
  1508. if ( Flags == SCEJET_EXACT_MATCH )
  1509. SeekFlag = SCEJET_SEEK_EQ;
  1510. else
  1511. SeekFlag = SCEJET_SEEK_EQ_NO_CASE;
  1512. rc = SceJetSeek(
  1513. hSection,
  1514. LinePrefix,
  1515. Len,
  1516. SeekFlag
  1517. );
  1518. break;
  1519. case SCEJET_PREFIX_MATCH:
  1520. case SCEJET_PREFIX_MATCH_NO_CASE:
  1521. if ( LinePrefix != NULL ) {
  1522. Len = wcslen(LinePrefix)*sizeof(WCHAR);
  1523. if ( Len > SCEJET_PREFIX_MAXLEN )
  1524. return(SCESTATUS_PREFIX_OVERFLOW);
  1525. } else {
  1526. Len = 0;
  1527. }
  1528. if ( Flags == SCEJET_PREFIX_MATCH )
  1529. SeekFlag = SCEJET_SEEK_GE;
  1530. else
  1531. SeekFlag = SCEJET_SEEK_GE_NO_CASE;
  1532. rc = SceJetSeek(
  1533. hSection,
  1534. LinePrefix,
  1535. Len,
  1536. SeekFlag
  1537. );
  1538. if ( rc == SCESTATUS_SUCCESS ) {
  1539. //
  1540. // remember the find context
  1541. //
  1542. if ( Len > 247 ) {
  1543. //
  1544. // in reality JET doesn't allow keys of more than 255 bytes
  1545. //
  1546. wcsncpy(FindContext.Prefix, LinePrefix, SCEJET_PREFIX_MAXLEN-2);
  1547. if ( Flags == SCEJET_PREFIX_MATCH_NO_CASE )
  1548. _wcslwr(FindContext.Prefix);
  1549. FindContext.Length = Len;
  1550. }
  1551. //
  1552. // set the upper range limit
  1553. //
  1554. JetErr = SceJetpBuildUpperLimit(
  1555. hSection,
  1556. LinePrefix,
  1557. Len,
  1558. (Flags == SCEJET_PREFIX_MATCH)
  1559. );
  1560. rc = SceJetJetErrorToSceStatus(JetErr);
  1561. }
  1562. break;
  1563. case SCEJET_NEXT_LINE:
  1564. //
  1565. // Move to next line
  1566. //
  1567. JetErr = JetMove(hSection->JetSessionID,
  1568. hSection->JetTableID,
  1569. JET_MoveNext,
  1570. 0);
  1571. //
  1572. // compare to the prefix
  1573. //
  1574. if ( JetErr == JET_errSuccess && FindContext.Length > 0 ) {
  1575. #ifdef SCEJET_DBG
  1576. printf("NextLine: Length is greater than 247\n");
  1577. #endif
  1578. JetErr = SceJetpCompareLine(
  1579. hSection,
  1580. JET_bitSeekGE,
  1581. FindContext.Prefix,
  1582. FindContext.Length,
  1583. &Result,
  1584. NULL
  1585. );
  1586. if ( JetErr == JET_errSuccess && Result != 0 )
  1587. JetErr = JET_errRecordNotFound;
  1588. }
  1589. rc = SceJetJetErrorToSceStatus(JetErr);
  1590. break;
  1591. default:
  1592. //
  1593. // Everything else passed in is treated as the current line
  1594. //
  1595. rc = SCESTATUS_SUCCESS;
  1596. break;
  1597. }
  1598. if ( rc != SCESTATUS_SUCCESS )
  1599. return(rc);
  1600. //
  1601. // Get this line's value
  1602. //
  1603. RetInfo.ibLongValue = 0;
  1604. RetInfo.itagSequence = 1;
  1605. RetInfo.cbStruct = sizeof(JET_RETINFO);
  1606. if ( ActualName != NULL || RetNameLen != NULL ) {
  1607. //
  1608. // get name field (long binary)
  1609. // if ActualName is NULL, then get the actual bytes
  1610. //
  1611. if ( ActualName != NULL ) {
  1612. Len = NameBufLen;
  1613. pTemp = (void *)ActualName;
  1614. } else {
  1615. Len = 256;
  1616. pTemp = (void *)Buffer;
  1617. }
  1618. JetErr = JetRetrieveColumn(
  1619. hSection->JetSessionID,
  1620. hSection->JetTableID,
  1621. hSection->JetColumnNameID,
  1622. pTemp,
  1623. Len,
  1624. RetNameLen,
  1625. 0,
  1626. &RetInfo
  1627. );
  1628. #ifdef SCEJET_DBG
  1629. printf("\tJetErr=%d, Len=%d, RetNameLen=%d\n", JetErr, Len, *RetNameLen);
  1630. #endif
  1631. rc = SceJetJetErrorToSceStatus(JetErr);
  1632. if ( rc == SCESTATUS_BUFFER_TOO_SMALL ) {
  1633. //
  1634. // if only length is requested, don't care buffer_too_small
  1635. //
  1636. if ( ActualName == NULL )
  1637. rc = SCESTATUS_SUCCESS;
  1638. }
  1639. if ( rc != SCESTATUS_SUCCESS &&
  1640. rc != SCESTATUS_BUFFER_TOO_SMALL )
  1641. return(rc);
  1642. }
  1643. if ( Value != NULL || RetValueLen != NULL ) {
  1644. //
  1645. // Get value field
  1646. // if Value is NULL, then get the actual bytes
  1647. //
  1648. if ( Value != NULL ) {
  1649. Len = ValueBufLen;
  1650. pTemp = (PVOID)Value;
  1651. } else {
  1652. Len = 256;
  1653. pTemp = (PVOID)Buffer;
  1654. }
  1655. JetErr = JetRetrieveColumn(
  1656. hSection->JetSessionID,
  1657. hSection->JetTableID,
  1658. hSection->JetColumnValueID,
  1659. pTemp,
  1660. Len,
  1661. RetValueLen,
  1662. 0,
  1663. &RetInfo
  1664. );
  1665. #ifdef SCEJET_DBG
  1666. printf("\tJetErr=%d, Len=%d, RetValueLen=%d\n", JetErr, Len, *RetValueLen);
  1667. #endif
  1668. rc1 = SceJetJetErrorToSceStatus(JetErr);
  1669. if ( rc1 == SCESTATUS_BUFFER_TOO_SMALL ) {
  1670. //
  1671. // if only length is requested, don't care buffer_too_small
  1672. //
  1673. if ( Value == NULL )
  1674. rc1 = SCESTATUS_SUCCESS;
  1675. }
  1676. if ( rc1 != SCESTATUS_SUCCESS &&
  1677. rc1 != SCESTATUS_BUFFER_TOO_SMALL )
  1678. return(rc1);
  1679. //
  1680. // rc is the status from retrieving Name field
  1681. //
  1682. if ( rc != SCESTATUS_SUCCESS )
  1683. return(rc);
  1684. else
  1685. return(rc1);
  1686. }
  1687. return(rc);
  1688. }
  1689. SCESTATUS
  1690. SceJetSetLine(
  1691. IN PSCESECTION hSection,
  1692. IN PWSTR Name,
  1693. IN BOOL bReserveCase,
  1694. IN PWSTR Value,
  1695. IN DWORD ValueLen,
  1696. IN LONG GpoID
  1697. )
  1698. /* ++
  1699. Fucntion Description:
  1700. This routine writes the Name and Value to the section (hSection).
  1701. If a exact matched name is found, overwrite, else insert a new
  1702. record.
  1703. Arguments:
  1704. hSection - The context handle of the section
  1705. Name - The info set to Column "Name"
  1706. Value - The info set to Column "Value"
  1707. Return Value:
  1708. SCESTATUS_SUCCESS
  1709. SCESTATUS_INVALID_PARAMETER
  1710. SCESTATUS_OTHER_ERROR
  1711. SCESTATUS_ACCESS_DENIED
  1712. SCESTATUS_DATA_OVERFLOW
  1713. -- */
  1714. {
  1715. JET_ERR JetErr;
  1716. DWORD Len;
  1717. SCESTATUS rc;
  1718. DWORD prep;
  1719. JET_SETINFO SetInfo;
  1720. PWSTR LwrName=NULL;
  1721. if ( hSection == NULL ||
  1722. Name == NULL ) {
  1723. return(SCESTATUS_INVALID_PARAMETER);
  1724. }
  1725. Len = wcslen(Name)*sizeof(WCHAR);
  1726. if ( Len <= 0 ) {
  1727. return(SCESTATUS_INVALID_PARAMETER);
  1728. }
  1729. if ( bReserveCase ) {
  1730. LwrName = Name;
  1731. } else {
  1732. //
  1733. // lower cased
  1734. //
  1735. LwrName = (PWSTR)ScepAlloc(0, Len+2);
  1736. if ( LwrName == NULL ) {
  1737. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  1738. }
  1739. wcscpy(LwrName, Name);
  1740. LwrName = _wcslwr(LwrName);
  1741. }
  1742. SetInfo.cbStruct = sizeof(JET_SETINFO);
  1743. SetInfo.itagSequence = 1;
  1744. SetInfo.ibLongValue = 0;
  1745. //
  1746. // check to see if the same key name already exists
  1747. //
  1748. JetErr = SceJetpSeek(
  1749. hSection,
  1750. LwrName,
  1751. Len,
  1752. SCEJET_SEEK_EQ,
  1753. FALSE
  1754. );
  1755. if ( JetErr == JET_errSuccess ||
  1756. JetErr == JET_errRecordNotFound ) {
  1757. if ( JetErr == JET_errSuccess )
  1758. // find a match. overwrite the value
  1759. prep = JET_prepReplace;
  1760. else
  1761. // no match. prepare the record for insertion
  1762. prep = JET_prepInsert;
  1763. JetErr = JetBeginTransaction(hSection->JetSessionID);
  1764. if ( JetErr == JET_errSuccess ) {
  1765. JetErr = JetPrepareUpdate(hSection->JetSessionID,
  1766. hSection->JetTableID,
  1767. prep
  1768. );
  1769. if ( JetErr != JET_errSuccess ) {
  1770. //
  1771. // rollback the transaction
  1772. //
  1773. JetRollback(hSection->JetSessionID,0);
  1774. }
  1775. }
  1776. }
  1777. if ( JetErr != JET_errSuccess)
  1778. return(SceJetJetErrorToSceStatus(JetErr));
  1779. if ( prep == JET_prepInsert ) {
  1780. //
  1781. // set the sectionID column
  1782. //
  1783. JetErr = JetSetColumn(
  1784. hSection->JetSessionID,
  1785. hSection->JetTableID,
  1786. hSection->JetColumnSectionID,
  1787. (void *)&(hSection->SectionID),
  1788. 8,
  1789. 0, //JET_bitSetOverwriteLV,
  1790. NULL
  1791. );
  1792. if ( JetErr == JET_errSuccess ) {
  1793. //
  1794. // set the new key in "Name" column
  1795. //
  1796. JetErr = JetSetColumn(
  1797. hSection->JetSessionID,
  1798. hSection->JetTableID,
  1799. hSection->JetColumnNameID,
  1800. (void *)LwrName,
  1801. Len,
  1802. 0, //JET_bitSetOverwriteLV,
  1803. &SetInfo
  1804. );
  1805. }
  1806. }
  1807. rc = SceJetJetErrorToSceStatus(JetErr);
  1808. if ( rc == SCESTATUS_SUCCESS ) {
  1809. //
  1810. // set value column
  1811. //
  1812. JetErr = JetSetColumn(
  1813. hSection->JetSessionID,
  1814. hSection->JetTableID,
  1815. hSection->JetColumnValueID,
  1816. (void *)Value,
  1817. ValueLen,
  1818. 0, //JET_bitSetOverwriteLV,
  1819. &SetInfo
  1820. );
  1821. if ( JetErr == JET_errSuccess ) {
  1822. //
  1823. // if GPO ID is provided and there is a GPOID column, set it
  1824. //
  1825. if ( GpoID > 0 && hSection->JetColumnGpoID > 0 ) {
  1826. JetErr = JetSetColumn(
  1827. hSection->JetSessionID,
  1828. hSection->JetTableID,
  1829. hSection->JetColumnGpoID,
  1830. (void *)&GpoID,
  1831. sizeof(LONG),
  1832. 0,
  1833. NULL
  1834. );
  1835. if ( JET_errColumnNotUpdatable == JetErr ) {
  1836. JetErr = JET_errSuccess;
  1837. }
  1838. }
  1839. // else
  1840. // if can't find the column, ignore the error
  1841. //
  1842. if ( JET_errSuccess == JetErr ) {
  1843. //
  1844. // Setting columns succeed. Update the record
  1845. //
  1846. JetErr = JetUpdate(hSection->JetSessionID,
  1847. hSection->JetTableID,
  1848. NULL,
  1849. 0,
  1850. &Len
  1851. );
  1852. }
  1853. }
  1854. rc = SceJetJetErrorToSceStatus(JetErr);
  1855. }
  1856. if ( rc == SCESTATUS_SUCCESS )
  1857. JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
  1858. if ( rc != SCESTATUS_SUCCESS ) {
  1859. //
  1860. // if setting fails, cancel the prepared record
  1861. //
  1862. JetPrepareUpdate(hSection->JetSessionID,
  1863. hSection->JetTableID,
  1864. JET_prepCancel
  1865. );
  1866. //
  1867. // Rollback the transaction
  1868. //
  1869. JetRollback(hSection->JetSessionID,0);
  1870. }
  1871. if ( LwrName != Name ) {
  1872. ScepFree(LwrName);
  1873. }
  1874. return(rc);
  1875. }
  1876. //
  1877. // Exported helper APIs
  1878. //
  1879. SCESTATUS
  1880. SceJetCreateTable(
  1881. IN PSCECONTEXT cxtProfile,
  1882. IN LPSTR tblName,
  1883. IN SCEJET_TABLE_TYPE tblType,
  1884. IN SCEJET_CREATE_FLAG nFlags,
  1885. OUT JET_TABLEID *TableID OPTIONAL,
  1886. OUT JET_COLUMNID *ColumnID OPTIONAL
  1887. )
  1888. /* ++
  1889. Routine Description:
  1890. This routine creates a table in the database opened in the context handle.
  1891. SCP/SAP/SMP tables created in the database have 3 columns: Section, Name,
  1892. and Value, with one index "SectionKey" which is Section+Name ascending.
  1893. Version table has only one column "Version".
  1894. Arguments:
  1895. cxtProfile - The context handle
  1896. tblName - ASCII name of the table to create
  1897. tblType - The type of the table. It may be one of the following
  1898. SCEJET_TABLE_SCP
  1899. SCEJET_TABLE_SAP
  1900. SCEJET_TABLE_SMP
  1901. SCEJET_TABLE_VERSION
  1902. SCEJET_TABLE_SECTION
  1903. SCEJET_TABLE_TATTOO
  1904. SCEJET_TABLE_GPO
  1905. TableID - SmTblVersion table id when tblType = SCEJET_TABLE_VERSION.
  1906. ColumnID - The column ID for Version when tblType = SCEJET_TABLE_VERSION
  1907. Return value:
  1908. SCESTATUS_SUCCESS
  1909. SCESTATUS_INVALID_PARAMETER
  1910. SCESTATUS_OBJECT_EXIST
  1911. SCESTATUS_BAD_FORMAT
  1912. SCESTATUS_OTHER_ERROR
  1913. -- */
  1914. {
  1915. JET_ERR JetErr;
  1916. SCESTATUS rc;
  1917. JET_TABLECREATE TableCreate;
  1918. JET_COLUMNCREATE ColumnCreate[5];
  1919. JET_INDEXCREATE IndexCreate[2];
  1920. DWORD numColumns;
  1921. if ( cxtProfile == NULL || tblName == NULL ) {
  1922. return(SCESTATUS_INVALID_PARAMETER);
  1923. }
  1924. if ( TableID ) {
  1925. *TableID = JET_tableidNil;
  1926. }
  1927. if ( ColumnID ) {
  1928. *ColumnID = 0;
  1929. }
  1930. switch ( tblType ) {
  1931. case SCEJET_TABLE_VERSION:
  1932. if ( TableID == NULL || ColumnID == NULL )
  1933. return(SCESTATUS_INVALID_PARAMETER);
  1934. //
  1935. // There is only one column in this table
  1936. //
  1937. ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
  1938. ColumnCreate[0].szColumnName = "Version";
  1939. ColumnCreate[0].coltyp = JET_coltypIEEESingle;
  1940. ColumnCreate[0].cbMax = 4;
  1941. ColumnCreate[0].grbit = JET_bitColumnNotNULL;
  1942. ColumnCreate[0].pvDefault = NULL;
  1943. ColumnCreate[0].cbDefault = 0;
  1944. ColumnCreate[0].cp = 0;
  1945. ColumnCreate[0].columnid = 0;
  1946. ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
  1947. ColumnCreate[1].szColumnName = "AnalyzeTimeStamp";
  1948. ColumnCreate[1].coltyp = JET_coltypBinary;
  1949. ColumnCreate[1].cbMax = 16; // should be 8 bytes - change later
  1950. ColumnCreate[1].grbit = 0;
  1951. ColumnCreate[1].pvDefault = NULL;
  1952. ColumnCreate[1].cbDefault = 0;
  1953. ColumnCreate[1].cp = 0;
  1954. ColumnCreate[1].columnid = 0;
  1955. ColumnCreate[2].cbStruct = sizeof(JET_COLUMNCREATE);
  1956. ColumnCreate[2].szColumnName = "ConfigTimeStamp";
  1957. ColumnCreate[2].coltyp = JET_coltypBinary;
  1958. ColumnCreate[2].cbMax = 16; // should be 8 bytes - change later
  1959. ColumnCreate[2].grbit = 0;
  1960. ColumnCreate[2].pvDefault = NULL;
  1961. ColumnCreate[2].cbDefault = 0;
  1962. ColumnCreate[2].cp = 0;
  1963. ColumnCreate[2].columnid = 0;
  1964. ColumnCreate[3].cbStruct = sizeof(JET_COLUMNCREATE);
  1965. ColumnCreate[3].szColumnName = "LastUsedMergeTable";
  1966. ColumnCreate[3].coltyp = JET_coltypLong;
  1967. ColumnCreate[3].cbMax = 4;
  1968. ColumnCreate[3].grbit = 0;
  1969. ColumnCreate[3].pvDefault = NULL;
  1970. ColumnCreate[3].cbDefault = 0;
  1971. ColumnCreate[3].cp = 0;
  1972. ColumnCreate[3].columnid = 0;
  1973. ColumnCreate[4].cbStruct = sizeof(JET_COLUMNCREATE);
  1974. ColumnCreate[4].szColumnName = "ProfileDescription";
  1975. ColumnCreate[4].coltyp = JET_coltypLongBinary;
  1976. ColumnCreate[4].cbMax = 1024;
  1977. ColumnCreate[4].grbit = 0;
  1978. ColumnCreate[4].pvDefault = NULL;
  1979. ColumnCreate[4].cbDefault = 0;
  1980. ColumnCreate[4].cp = 0;
  1981. ColumnCreate[4].columnid = 0;
  1982. //
  1983. // Assign table info
  1984. //
  1985. TableCreate.cbStruct = sizeof(JET_TABLECREATE);
  1986. TableCreate.szTableName = tblName;
  1987. TableCreate.szTemplateTableName = NULL;
  1988. TableCreate.ulPages = 1;
  1989. TableCreate.ulDensity = 90;
  1990. TableCreate.rgcolumncreate = ColumnCreate;
  1991. TableCreate.cColumns = 5;
  1992. TableCreate.rgindexcreate = NULL;
  1993. TableCreate.cIndexes = 0;
  1994. TableCreate.grbit = 0;
  1995. TableCreate.tableid = 0;
  1996. break;
  1997. case SCEJET_TABLE_SCP:
  1998. case SCEJET_TABLE_SAP:
  1999. case SCEJET_TABLE_SMP:
  2000. case SCEJET_TABLE_TATTOO:
  2001. //
  2002. // There are 3 columns in each table.
  2003. // Assign each column info
  2004. //
  2005. ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
  2006. ColumnCreate[0].szColumnName = "SectionID";
  2007. ColumnCreate[0].coltyp = JET_coltypIEEEDouble;
  2008. ColumnCreate[0].cbMax = 8;
  2009. ColumnCreate[0].grbit = JET_bitColumnNotNULL;
  2010. ColumnCreate[0].pvDefault = NULL;
  2011. ColumnCreate[0].cbDefault = 0;
  2012. ColumnCreate[0].cp = 0;
  2013. ColumnCreate[0].columnid = 0;
  2014. ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
  2015. ColumnCreate[1].szColumnName = "Name";
  2016. ColumnCreate[1].coltyp = JET_coltypLongBinary;
  2017. ColumnCreate[1].cbMax = 1024;
  2018. ColumnCreate[1].grbit = 0; //JET_bitColumnNotNULL;
  2019. ColumnCreate[1].pvDefault = NULL;
  2020. ColumnCreate[1].cbDefault = 0;
  2021. ColumnCreate[1].cp = 0;
  2022. ColumnCreate[1].columnid = 0;
  2023. ColumnCreate[2].cbStruct = sizeof(JET_COLUMNCREATE);
  2024. ColumnCreate[2].szColumnName = "Value";
  2025. ColumnCreate[2].coltyp = JET_coltypLongBinary;
  2026. ColumnCreate[2].cbMax = (unsigned long)0x7FFFFFFF; // 2GB
  2027. ColumnCreate[2].grbit = 0;
  2028. ColumnCreate[2].pvDefault = NULL;
  2029. ColumnCreate[2].cbDefault = 0;
  2030. ColumnCreate[2].cp = 0;
  2031. ColumnCreate[2].columnid = 0;
  2032. numColumns = 3;
  2033. if ( tblType == SCEJET_TABLE_SCP ) {
  2034. ColumnCreate[3].cbStruct = sizeof(JET_COLUMNCREATE);
  2035. ColumnCreate[3].szColumnName = "GpoID";
  2036. ColumnCreate[3].coltyp = JET_coltypLong;
  2037. ColumnCreate[3].cbMax = 4;
  2038. ColumnCreate[3].grbit = 0;
  2039. ColumnCreate[3].pvDefault = NULL;
  2040. ColumnCreate[3].cbDefault = 0;
  2041. ColumnCreate[3].cp = 0;
  2042. ColumnCreate[3].columnid = 0;
  2043. numColumns = 4;
  2044. }
  2045. //
  2046. // Assign index info - one index in each table.
  2047. //
  2048. memset(IndexCreate, 0, sizeof(JET_INDEXCREATE) );
  2049. IndexCreate[0].cbStruct = sizeof(JET_INDEXCREATE);
  2050. IndexCreate[0].szIndexName = "SectionKey";
  2051. IndexCreate[0].szKey = "+SectionID\0+Name\0\0";
  2052. IndexCreate[0].cbKey = 18;
  2053. IndexCreate[0].grbit = 0; // JET_bitIndexPrimary; // | JET_bitIndexUnique;
  2054. IndexCreate[0].ulDensity = 50;
  2055. //
  2056. // Assign table info
  2057. //
  2058. TableCreate.cbStruct = sizeof(JET_TABLECREATE);
  2059. TableCreate.szTableName = tblName;
  2060. TableCreate.szTemplateTableName = NULL;
  2061. TableCreate.ulPages = 20;
  2062. TableCreate.ulDensity = 50;
  2063. TableCreate.rgcolumncreate = ColumnCreate;
  2064. TableCreate.cColumns = numColumns;
  2065. TableCreate.rgindexcreate = IndexCreate;
  2066. TableCreate.cIndexes = 1;
  2067. TableCreate.grbit = 0;
  2068. TableCreate.tableid = 0;
  2069. break;
  2070. case SCEJET_TABLE_SECTION:
  2071. //
  2072. // There are 2 columns in this table.
  2073. // Assign each column info
  2074. //
  2075. ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
  2076. ColumnCreate[0].szColumnName = "SectionID";
  2077. ColumnCreate[0].coltyp = JET_coltypIEEEDouble;
  2078. ColumnCreate[0].cbMax = 8;
  2079. ColumnCreate[0].grbit = JET_bitColumnNotNULL;
  2080. ColumnCreate[0].pvDefault = NULL;
  2081. ColumnCreate[0].cbDefault = 0;
  2082. ColumnCreate[0].cp = 0;
  2083. ColumnCreate[0].columnid = 0;
  2084. ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
  2085. ColumnCreate[1].szColumnName = "Name";
  2086. ColumnCreate[1].coltyp = JET_coltypBinary;
  2087. ColumnCreate[1].cbMax = 255;
  2088. ColumnCreate[1].grbit = JET_bitColumnNotNULL;
  2089. ColumnCreate[1].pvDefault = NULL;
  2090. ColumnCreate[1].cbDefault = 0;
  2091. ColumnCreate[1].cp = 0;
  2092. ColumnCreate[1].columnid = 0;
  2093. //
  2094. // Assign index info - one index in each table.
  2095. //
  2096. memset(IndexCreate, 0, 2*sizeof(JET_INDEXCREATE) );
  2097. IndexCreate[0].cbStruct = sizeof(JET_INDEXCREATE);
  2098. IndexCreate[0].szIndexName = "SectionKey";
  2099. IndexCreate[0].szKey = "+Name\0\0";
  2100. IndexCreate[0].cbKey = 7;
  2101. IndexCreate[0].grbit = JET_bitIndexPrimary; // | JET_bitIndexUnique;
  2102. IndexCreate[0].ulDensity = 80;
  2103. IndexCreate[1].cbStruct = sizeof(JET_INDEXCREATE);
  2104. IndexCreate[1].szIndexName = "SecID";
  2105. IndexCreate[1].szKey = "+SectionID\0\0";
  2106. IndexCreate[1].cbKey = 12;
  2107. IndexCreate[1].grbit = 0;
  2108. IndexCreate[1].ulDensity = 80;
  2109. //
  2110. // Assign table info
  2111. //
  2112. TableCreate.cbStruct = sizeof(JET_TABLECREATE);
  2113. TableCreate.szTableName = tblName;
  2114. TableCreate.szTemplateTableName = NULL;
  2115. TableCreate.ulPages = 10;
  2116. TableCreate.ulDensity = 80;
  2117. TableCreate.rgcolumncreate = ColumnCreate;
  2118. TableCreate.cColumns = 2;
  2119. TableCreate.rgindexcreate = IndexCreate;
  2120. TableCreate.cIndexes = 2;
  2121. TableCreate.grbit = 0;
  2122. TableCreate.tableid = 0;
  2123. break;
  2124. case SCEJET_TABLE_GPO:
  2125. //
  2126. // There are 3 columns in this table.
  2127. // Assign each column info
  2128. //
  2129. ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
  2130. ColumnCreate[0].szColumnName = "GpoID";
  2131. ColumnCreate[0].coltyp = JET_coltypLong;
  2132. ColumnCreate[0].cbMax = 4;
  2133. ColumnCreate[0].grbit = JET_bitColumnNotNULL;
  2134. ColumnCreate[0].pvDefault = NULL;
  2135. ColumnCreate[0].cbDefault = 0;
  2136. ColumnCreate[0].cp = 0;
  2137. ColumnCreate[0].columnid = 0;
  2138. ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
  2139. ColumnCreate[1].szColumnName = "Name";
  2140. ColumnCreate[1].coltyp = JET_coltypBinary;
  2141. ColumnCreate[1].cbMax = 255;
  2142. ColumnCreate[1].grbit = JET_bitColumnNotNULL;
  2143. ColumnCreate[1].pvDefault = NULL;
  2144. ColumnCreate[1].cbDefault = 0;
  2145. ColumnCreate[1].cp = 0;
  2146. ColumnCreate[1].columnid = 0;
  2147. ColumnCreate[2].cbStruct = sizeof(JET_COLUMNCREATE);
  2148. ColumnCreate[2].szColumnName = "DisplayName";
  2149. ColumnCreate[2].coltyp = JET_coltypBinary;
  2150. ColumnCreate[2].cbMax = 255;
  2151. ColumnCreate[2].grbit = 0;
  2152. ColumnCreate[2].pvDefault = NULL;
  2153. ColumnCreate[2].cbDefault = 0;
  2154. ColumnCreate[2].cp = 0;
  2155. ColumnCreate[2].columnid = 0;
  2156. //
  2157. // Assign index info - one index in each table.
  2158. //
  2159. memset(IndexCreate, 0, 2*sizeof(JET_INDEXCREATE) );
  2160. IndexCreate[0].cbStruct = sizeof(JET_INDEXCREATE);
  2161. IndexCreate[0].szIndexName = "SectionKey";
  2162. IndexCreate[0].szKey = "+GpoID\0\0";
  2163. IndexCreate[0].cbKey = 8;
  2164. IndexCreate[0].grbit = JET_bitIndexPrimary; // | JET_bitIndexUnique;
  2165. IndexCreate[0].ulDensity = 80;
  2166. IndexCreate[1].cbStruct = sizeof(JET_INDEXCREATE);
  2167. IndexCreate[1].szIndexName = "GpoName";
  2168. IndexCreate[1].szKey = "+Name\0\0";
  2169. IndexCreate[1].cbKey = 7;
  2170. IndexCreate[1].grbit = 0;
  2171. IndexCreate[1].ulDensity = 80;
  2172. //
  2173. // Assign table info
  2174. //
  2175. TableCreate.cbStruct = sizeof(JET_TABLECREATE);
  2176. TableCreate.szTableName = tblName;
  2177. TableCreate.szTemplateTableName = NULL;
  2178. TableCreate.ulPages = 10;
  2179. TableCreate.ulDensity = 80;
  2180. TableCreate.rgcolumncreate = ColumnCreate;
  2181. TableCreate.cColumns = 3;
  2182. TableCreate.rgindexcreate = IndexCreate;
  2183. TableCreate.cIndexes = 2;
  2184. TableCreate.grbit = 0;
  2185. TableCreate.tableid = 0;
  2186. break;
  2187. default:
  2188. return(SCESTATUS_INVALID_PARAMETER);
  2189. }
  2190. //
  2191. // Create the table, column, and index together
  2192. //
  2193. JetErr = JetCreateTableColumnIndex(
  2194. cxtProfile->JetSessionID,
  2195. cxtProfile->JetDbID,
  2196. &TableCreate
  2197. );
  2198. rc = SceJetJetErrorToSceStatus(JetErr);
  2199. if ( SCESTATUS_OBJECT_EXIST == rc &&
  2200. TableCreate.tableid != JET_tableidNil ) {
  2201. rc = SCESTATUS_SUCCESS;
  2202. } else if ( rc == SCESTATUS_SUCCESS &&
  2203. TableCreate.tableid == JET_tableidNil ) {
  2204. rc = SCESTATUS_OTHER_ERROR;
  2205. }
  2206. if ( rc == SCESTATUS_SUCCESS ) {
  2207. //
  2208. // Save the tableid and columnid in the context
  2209. //
  2210. if ( SCEJET_CREATE_NO_TABLEID == nFlags ) {
  2211. //
  2212. // do not need table ID to be returned
  2213. //
  2214. if ( TableCreate.tableid != JET_tableidNil ) {
  2215. JetCloseTable(
  2216. cxtProfile->JetSessionID,
  2217. TableCreate.tableid
  2218. );
  2219. }
  2220. } else {
  2221. if ( tblType == SCEJET_TABLE_VERSION ) {
  2222. *TableID = TableCreate.tableid;
  2223. *ColumnID = ColumnCreate[0].columnid;
  2224. } else if ( TableID ) {
  2225. *TableID = TableCreate.tableid;
  2226. } else {
  2227. switch ( tblType ) {
  2228. case SCEJET_TABLE_SCP:
  2229. cxtProfile->JetScpID = TableCreate.tableid;
  2230. cxtProfile->JetScpSectionID = ColumnCreate[0].columnid;
  2231. cxtProfile->JetScpNameID = ColumnCreate[1].columnid;
  2232. cxtProfile->JetScpValueID = ColumnCreate[2].columnid;
  2233. cxtProfile->JetScpGpoID = ColumnCreate[3].columnid;
  2234. break;
  2235. case SCEJET_TABLE_SMP:
  2236. cxtProfile->JetSmpID = TableCreate.tableid;
  2237. cxtProfile->JetSmpSectionID = ColumnCreate[0].columnid;
  2238. cxtProfile->JetSmpNameID = ColumnCreate[1].columnid;
  2239. cxtProfile->JetSmpValueID = ColumnCreate[2].columnid;
  2240. break;
  2241. case SCEJET_TABLE_SAP:
  2242. case SCEJET_TABLE_TATTOO: // use the SAP handle
  2243. cxtProfile->JetSapID = TableCreate.tableid;
  2244. cxtProfile->JetSapSectionID = ColumnCreate[0].columnid;
  2245. cxtProfile->JetSapNameID = ColumnCreate[1].columnid;
  2246. cxtProfile->JetSapValueID = ColumnCreate[2].columnid;
  2247. break;
  2248. case SCEJET_TABLE_SECTION:
  2249. cxtProfile->JetTblSecID = TableCreate.tableid;
  2250. cxtProfile->JetSecNameID = ColumnCreate[1].columnid;
  2251. cxtProfile->JetSecID = ColumnCreate[0].columnid;
  2252. break;
  2253. }
  2254. }
  2255. if ( tblType != SCEJET_TABLE_VERSION ) {
  2256. //
  2257. // Set current index in this table
  2258. //
  2259. JetErr = JetSetCurrentIndex(
  2260. cxtProfile->JetSessionID,
  2261. TableCreate.tableid,
  2262. "SectionKey"
  2263. );
  2264. rc = SceJetJetErrorToSceStatus(JetErr);
  2265. }
  2266. }
  2267. }
  2268. return(rc);
  2269. }
  2270. SCESTATUS
  2271. SceJetOpenTable(
  2272. IN PSCECONTEXT cxtProfile,
  2273. IN LPSTR tblName,
  2274. IN SCEJET_TABLE_TYPE tblType,
  2275. IN SCEJET_OPEN_TYPE OpenType,
  2276. OUT JET_TABLEID *TableID
  2277. )
  2278. /* ++
  2279. Routine Description:
  2280. This routine opens a table, gets column IDs for the column "Name" and
  2281. "Value" and saves them in the context.
  2282. Arguments:
  2283. cxtProfile - The context handle
  2284. tblName - ASCII name of a table to open
  2285. tblType - The type of the table. It may be one of the following
  2286. SCEJET_TABLE_SCP
  2287. SCEJET_TABLE_SAP
  2288. SCEJET_TABLE_SMP
  2289. SCEJET_TABLE_VERSION
  2290. SCEJET_TABLE_SECTION
  2291. SCEJET_TABLE_GPO
  2292. SCEJET_TABLE_TATTOO
  2293. Return value:
  2294. SCESTATUS_SUCCESS
  2295. SCESTATUS_INVALID_PARAMETER
  2296. SCESTATUS_BAD_FORMAT
  2297. SCESTATUS_ACCESS_DENIED
  2298. SCESTATUS_NOT_ENOUGH_RESOURCE
  2299. SCESTATUS_OTHER_ERROR
  2300. -- */
  2301. {
  2302. JET_ERR JetErr;
  2303. JET_TABLEID *tblID;
  2304. JET_TABLEID tmpTblID;
  2305. JET_COLUMNDEF ColumnDef;
  2306. JET_COLUMNID NameID=0;
  2307. JET_COLUMNID ValueID=0;
  2308. JET_COLUMNID SectionID=0;
  2309. JET_COLUMNID GpoColID=0;
  2310. SCESTATUS rc;
  2311. JET_GRBIT grbit=0;
  2312. if ( cxtProfile == NULL || tblName == NULL )
  2313. return(SCESTATUS_INVALID_PARAMETER);
  2314. // get address of table id
  2315. if ( TableID ) {
  2316. tblID = TableID;
  2317. } else {
  2318. switch (tblType) {
  2319. case SCEJET_TABLE_SCP:
  2320. tblID = &(cxtProfile->JetScpID);
  2321. break;
  2322. case SCEJET_TABLE_SAP:
  2323. case SCEJET_TABLE_TATTOO:
  2324. tblID = &(cxtProfile->JetSapID);
  2325. break;
  2326. case SCEJET_TABLE_SMP:
  2327. tblID = &(cxtProfile->JetSmpID);
  2328. break;
  2329. case SCEJET_TABLE_SECTION:
  2330. tblID = &(cxtProfile->JetTblSecID);
  2331. break;
  2332. default:
  2333. return(SCESTATUS_INVALID_PARAMETER);
  2334. }
  2335. }
  2336. if ( OpenType == SCEJET_OPEN_READ_ONLY ) {
  2337. grbit = JET_bitTableReadOnly;
  2338. }
  2339. // open this table
  2340. JetErr = JetOpenTable(
  2341. cxtProfile->JetSessionID,
  2342. cxtProfile->JetDbID,
  2343. tblName,
  2344. NULL,
  2345. 0,
  2346. grbit,
  2347. &tmpTblID
  2348. );
  2349. rc = SceJetJetErrorToSceStatus(JetErr);
  2350. if ( rc == SCESTATUS_SUCCESS )
  2351. *tblID = tmpTblID;
  2352. if ( TableID ) {
  2353. return(rc);
  2354. }
  2355. if ( rc != SCESTATUS_SUCCESS ) {
  2356. //
  2357. // SCP and SMP table must exist. SAP and Tattoo tables are optional.
  2358. //
  2359. if ( tblType != SCEJET_TABLE_SCP &&
  2360. tblType != SCEJET_TABLE_SMP &&
  2361. tblType != SCEJET_TABLE_SECTION &&
  2362. ( rc == SCESTATUS_BAD_FORMAT ||
  2363. rc == SCESTATUS_PROFILE_NOT_FOUND) ) {
  2364. return(SCESTATUS_SUCCESS);
  2365. }
  2366. return(rc);
  2367. }
  2368. //
  2369. // get column id for Column "SectionID"
  2370. //
  2371. JetErr = JetGetTableColumnInfo(
  2372. cxtProfile->JetSessionID,
  2373. *tblID,
  2374. "SectionID",
  2375. (VOID *)&ColumnDef,
  2376. sizeof(JET_COLUMNDEF),
  2377. 0
  2378. );
  2379. rc = SceJetJetErrorToSceStatus(JetErr);
  2380. if ( rc != SCESTATUS_SUCCESS ) {
  2381. return(rc);
  2382. }
  2383. SectionID = ColumnDef.columnid;
  2384. //
  2385. // get column id for Column "Name"
  2386. //
  2387. JetErr = JetGetTableColumnInfo(
  2388. cxtProfile->JetSessionID,
  2389. *tblID,
  2390. "Name",
  2391. (VOID *)&ColumnDef,
  2392. sizeof(JET_COLUMNDEF),
  2393. 0
  2394. );
  2395. rc = SceJetJetErrorToSceStatus(JetErr);
  2396. if ( rc != SCESTATUS_SUCCESS ) {
  2397. return(rc);
  2398. }
  2399. NameID = ColumnDef.columnid;
  2400. if ( tblType == SCEJET_TABLE_SCP ||
  2401. tblType == SCEJET_TABLE_SAP ||
  2402. tblType == SCEJET_TABLE_SMP ||
  2403. tblType == SCEJET_TABLE_TATTOO ) {
  2404. //
  2405. // get column id for Column "Value"
  2406. //
  2407. JetErr = JetGetTableColumnInfo(
  2408. cxtProfile->JetSessionID,
  2409. *tblID,
  2410. "Value",
  2411. (VOID *)&ColumnDef,
  2412. sizeof(JET_COLUMNDEF),
  2413. 0
  2414. );
  2415. rc = SceJetJetErrorToSceStatus(JetErr);
  2416. if ( rc != SCESTATUS_SUCCESS ) {
  2417. return(rc);
  2418. }
  2419. ValueID = ColumnDef.columnid;
  2420. if ( tblType == SCEJET_TABLE_SCP ) {
  2421. //
  2422. // get column id for column GpoID
  2423. //
  2424. JetErr = JetGetTableColumnInfo(
  2425. cxtProfile->JetSessionID,
  2426. *tblID,
  2427. "GpoID",
  2428. (VOID *)&ColumnDef,
  2429. sizeof(JET_COLUMNDEF),
  2430. 0
  2431. );
  2432. rc = SceJetJetErrorToSceStatus(JetErr);
  2433. if ( rc != SCESTATUS_SUCCESS ) {
  2434. return(rc);
  2435. }
  2436. GpoColID = ColumnDef.columnid;
  2437. }
  2438. }
  2439. //
  2440. // save the column ids
  2441. //
  2442. switch (tblType) {
  2443. case SCEJET_TABLE_SCP:
  2444. cxtProfile->JetScpSectionID = SectionID;
  2445. cxtProfile->JetScpNameID = NameID;
  2446. cxtProfile->JetScpValueID = ValueID;
  2447. cxtProfile->JetScpGpoID = GpoColID;
  2448. break;
  2449. case SCEJET_TABLE_SAP:
  2450. case SCEJET_TABLE_TATTOO:
  2451. cxtProfile->JetSapSectionID = SectionID;
  2452. cxtProfile->JetSapNameID = NameID;
  2453. cxtProfile->JetSapValueID = ValueID;
  2454. break;
  2455. case SCEJET_TABLE_SMP:
  2456. cxtProfile->JetSmpSectionID = SectionID;
  2457. cxtProfile->JetSmpNameID = NameID;
  2458. cxtProfile->JetSmpValueID = ValueID;
  2459. break;
  2460. case SCEJET_TABLE_SECTION:
  2461. cxtProfile->JetSecID = SectionID;
  2462. cxtProfile->JetSecNameID = NameID;
  2463. }
  2464. //
  2465. // Set current index
  2466. //
  2467. JetErr = JetSetCurrentIndex(
  2468. cxtProfile->JetSessionID,
  2469. *tblID,
  2470. "SectionKey"
  2471. );
  2472. rc = SceJetJetErrorToSceStatus(JetErr);
  2473. return(rc);
  2474. }
  2475. SCESTATUS
  2476. SceJetDeleteTable(
  2477. IN PSCECONTEXT cxtProfile,
  2478. IN LPSTR tblName,
  2479. IN SCEJET_TABLE_TYPE tblType
  2480. )
  2481. {
  2482. JET_ERR JetErr;
  2483. JET_TABLEID *tblID;
  2484. SCESTATUS rc=SCESTATUS_SUCCESS;
  2485. if ( cxtProfile == NULL || tblName == NULL )
  2486. return(SCESTATUS_INVALID_PARAMETER);
  2487. // get address of table id
  2488. switch (tblType) {
  2489. case SCEJET_TABLE_SCP:
  2490. tblID = &(cxtProfile->JetScpID);
  2491. break;
  2492. case SCEJET_TABLE_SAP:
  2493. case SCEJET_TABLE_TATTOO:
  2494. tblID = &(cxtProfile->JetSapID);
  2495. break;
  2496. case SCEJET_TABLE_SMP:
  2497. tblID = &(cxtProfile->JetSmpID);
  2498. break;
  2499. case SCEJET_TABLE_SECTION:
  2500. tblID = &(cxtProfile->JetTblSecID);
  2501. break;
  2502. default:
  2503. return(SCESTATUS_INVALID_PARAMETER);
  2504. }
  2505. // close this table
  2506. if ( *tblID != JET_tableidNil ) {
  2507. JetErr = JetCloseTable(
  2508. cxtProfile->JetSessionID,
  2509. *tblID
  2510. );
  2511. rc = SceJetJetErrorToSceStatus(JetErr);
  2512. if ( rc != SCESTATUS_SUCCESS )
  2513. return(rc);
  2514. *tblID = JET_tableidNil;
  2515. //
  2516. // reset each column id
  2517. //
  2518. switch (tblType) {
  2519. case SCEJET_TABLE_SCP:
  2520. cxtProfile->JetScpSectionID = 0;
  2521. cxtProfile->JetScpNameID = 0;
  2522. cxtProfile->JetScpValueID = 0;
  2523. cxtProfile->JetScpGpoID = 0;
  2524. break;
  2525. case SCEJET_TABLE_SAP:
  2526. case SCEJET_TABLE_TATTOO:
  2527. cxtProfile->JetSapSectionID = 0;
  2528. cxtProfile->JetSapNameID = 0;
  2529. cxtProfile->JetSapValueID = 0;
  2530. break;
  2531. case SCEJET_TABLE_SMP:
  2532. cxtProfile->JetSmpSectionID = 0;
  2533. cxtProfile->JetSmpNameID = 0;
  2534. cxtProfile->JetSmpValueID = 0;
  2535. break;
  2536. case SCEJET_TABLE_SECTION:
  2537. cxtProfile->JetSecNameID = 0;
  2538. cxtProfile->JetSecID = 0;
  2539. break;
  2540. }
  2541. }
  2542. JetErr = JetDeleteTable(cxtProfile->JetSessionID,
  2543. cxtProfile->JetDbID,
  2544. tblName
  2545. );
  2546. rc = SceJetJetErrorToSceStatus(JetErr);
  2547. if ( rc == SCESTATUS_BAD_FORMAT )
  2548. rc = SCESTATUS_SUCCESS;
  2549. return(rc);
  2550. }
  2551. SCESTATUS
  2552. SceJetCheckVersion(
  2553. IN PSCECONTEXT cxtProfile,
  2554. OUT FLOAT *pVersion OPTIONAL
  2555. )
  2556. /* ++
  2557. Routine Description:
  2558. This routine checks the version table in the database to see if the
  2559. database is for the security manager, also if the version # is the
  2560. correct one.
  2561. The version table is named "SmTblVersion" and has a Version column
  2562. in it. The current version # is 1.2
  2563. Arguments:
  2564. cxtProfile - The profile context
  2565. Return Value:
  2566. SCESTATUS_SUCCESS
  2567. SCESTATUS_BAD_FORMAT
  2568. SCESTATUS_OTHER_ERROR
  2569. SCESTATUS from SceJetOpenTable
  2570. -- */
  2571. {
  2572. SCESTATUS rc;
  2573. FLOAT Version=(FLOAT)1.0;
  2574. DWORD Actual;
  2575. if ( cxtProfile == NULL ) {
  2576. return(SCESTATUS_INVALID_PARAMETER);
  2577. }
  2578. rc = SceJetpGetValueFromVersion(
  2579. cxtProfile,
  2580. "SmTblVersion",
  2581. "Version",
  2582. (LPSTR)&Version,
  2583. 4, // number of bytes
  2584. &Actual
  2585. );
  2586. if ( rc == SCESTATUS_SUCCESS ||
  2587. rc == SCESTATUS_BUFFER_TOO_SMALL ) {
  2588. if ( Version != (FLOAT)1.2 )
  2589. rc = SCESTATUS_BAD_FORMAT;
  2590. else
  2591. rc = SCESTATUS_SUCCESS;
  2592. }
  2593. if ( pVersion ) {
  2594. *pVersion = Version;
  2595. }
  2596. return(rc);
  2597. }
  2598. SCESTATUS
  2599. SceJetGetSectionIDByName(
  2600. IN PSCECONTEXT cxtProfile,
  2601. IN PCWSTR Name,
  2602. OUT DOUBLE *SectionID OPTIONAL
  2603. )
  2604. /* ++
  2605. Routine Description:
  2606. This routine retrieve the section ID for the name in the Section table.
  2607. If SectionID is NULL, this routine really does a seek by name. The cursor
  2608. will be on the record if there is a successful match.
  2609. Arguments:
  2610. cxtProfile - The profile context handle
  2611. Name - The section name looked for
  2612. SectionID - The output section ID if there is a successful match
  2613. Return Value:
  2614. SCESTATUS_SUCCESS
  2615. SCESTATUS_INVALID_PARAMETER
  2616. SCESTATUS_RECORD_NOT_FOUND
  2617. SCESTATUS_BAD_FORMAT
  2618. SCESTATUS_OTHER_ERROR
  2619. -- */
  2620. {
  2621. SCESTATUS rc;
  2622. JET_ERR JetErr;
  2623. DWORD Actual;
  2624. PWSTR LwrName=NULL;
  2625. DWORD Len;
  2626. if ( cxtProfile == NULL || Name == NULL )
  2627. return(SCESTATUS_INVALID_PARAMETER);
  2628. if ( cxtProfile->JetTblSecID <= 0) {
  2629. //
  2630. // Section table is not opened yet
  2631. //
  2632. rc = SceJetOpenTable(
  2633. cxtProfile,
  2634. "SmTblSection",
  2635. SCEJET_TABLE_SECTION,
  2636. SCEJET_OPEN_READ_ONLY,
  2637. NULL
  2638. );
  2639. if ( rc != SCESTATUS_SUCCESS )
  2640. return(rc);
  2641. }
  2642. //
  2643. // set current index to SectionKey (the name)
  2644. //
  2645. JetErr = JetSetCurrentIndex(
  2646. cxtProfile->JetSessionID,
  2647. cxtProfile->JetTblSecID,
  2648. "SectionKey"
  2649. );
  2650. rc = SceJetJetErrorToSceStatus(JetErr);
  2651. if ( rc != SCESTATUS_SUCCESS )
  2652. return(rc);
  2653. Len = wcslen(Name);
  2654. LwrName = (PWSTR)ScepAlloc(0, (Len+1)*sizeof(WCHAR));
  2655. if ( LwrName != NULL ) {
  2656. wcscpy(LwrName, Name);
  2657. LwrName = _wcslwr(LwrName);
  2658. JetErr = JetMakeKey(
  2659. cxtProfile->JetSessionID,
  2660. cxtProfile->JetTblSecID,
  2661. (VOID *)LwrName,
  2662. Len*sizeof(WCHAR),
  2663. JET_bitNewKey
  2664. );
  2665. if ( JetErr == JET_errKeyIsMade ) {
  2666. //
  2667. // Only one key is needed, it may return this code, even on success.
  2668. //
  2669. JetErr = JET_errSuccess;
  2670. }
  2671. rc = SceJetJetErrorToSceStatus(JetErr);
  2672. if ( rc == SCESTATUS_SUCCESS ) {
  2673. JetErr = JetSeek(
  2674. cxtProfile->JetSessionID,
  2675. cxtProfile->JetTblSecID,
  2676. JET_bitSeekEQ
  2677. );
  2678. rc = SceJetJetErrorToSceStatus(JetErr);
  2679. if ( rc == SCESTATUS_SUCCESS ) {
  2680. //
  2681. // find the section name, retrieve column SectionID
  2682. //
  2683. if ( SectionID != NULL) {
  2684. JetErr = JetRetrieveColumn(
  2685. cxtProfile->JetSessionID,
  2686. cxtProfile->JetTblSecID,
  2687. cxtProfile->JetSecID,
  2688. (void *)SectionID,
  2689. 8,
  2690. &Actual,
  2691. 0,
  2692. NULL
  2693. );
  2694. rc = SceJetJetErrorToSceStatus(JetErr);
  2695. }
  2696. }
  2697. }
  2698. ScepFree(LwrName);
  2699. } else
  2700. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2701. return(rc);
  2702. }
  2703. SCESTATUS
  2704. SceJetGetSectionNameByID(
  2705. IN PSCECONTEXT cxtProfile,
  2706. IN DOUBLE SectionID,
  2707. OUT PWSTR Name OPTIONAL,
  2708. IN OUT LPDWORD pNameLen OPTIONAL
  2709. )
  2710. /* ++
  2711. Routine Description:
  2712. This routine retrieve the section name for the ID in the Section table.
  2713. If Name is NULL, this routine really does a seek by ID. The cursor will
  2714. be on the record if there is a successful match.
  2715. Arguments:
  2716. cxtProfile - The profile context handle
  2717. SectionID - The section ID looking for
  2718. Name - The optional output buffer for section name
  2719. pNameLen - The name buffer's length
  2720. Return Value:
  2721. SCESTATUS_SUCCESS
  2722. SCESTATUS_INVALID_PARAMETER
  2723. SCESTATUS_RECORD_NOT_FOUND
  2724. SCESTATUS_BAD_FORMAT
  2725. SCESTATUS_OTHER_ERROR
  2726. -- */
  2727. {
  2728. SCESTATUS rc;
  2729. JET_ERR JetErr;
  2730. DWORD Actual;
  2731. if ( cxtProfile == NULL || (Name != NULL && pNameLen == NULL) )
  2732. return(SCESTATUS_INVALID_PARAMETER);
  2733. if ( cxtProfile->JetTblSecID <= 0) {
  2734. //
  2735. // Section table is not opened yet
  2736. //
  2737. rc = SceJetOpenTable(
  2738. cxtProfile,
  2739. "SmTblSection",
  2740. SCEJET_TABLE_SECTION,
  2741. SCEJET_OPEN_READ_ONLY,
  2742. NULL
  2743. );
  2744. if ( rc != SCESTATUS_SUCCESS )
  2745. return(rc);
  2746. }
  2747. //
  2748. // set current index to SecID (the ID)
  2749. //
  2750. JetErr = JetSetCurrentIndex(
  2751. cxtProfile->JetSessionID,
  2752. cxtProfile->JetTblSecID,
  2753. "SecID"
  2754. );
  2755. rc = SceJetJetErrorToSceStatus(JetErr);
  2756. if ( rc != SCESTATUS_SUCCESS )
  2757. return(rc);
  2758. JetErr = JetMakeKey(
  2759. cxtProfile->JetSessionID,
  2760. cxtProfile->JetTblSecID,
  2761. (VOID *)(&SectionID),
  2762. 8,
  2763. JET_bitNewKey
  2764. );
  2765. if ( JetErr == JET_errKeyIsMade ) {
  2766. //
  2767. // Only one key is needed, it may return this code, even on success.
  2768. //
  2769. JetErr = JET_errSuccess;
  2770. }
  2771. rc = SceJetJetErrorToSceStatus(JetErr);
  2772. if ( rc == SCESTATUS_SUCCESS ) {
  2773. JetErr = JetSeek(
  2774. cxtProfile->JetSessionID,
  2775. cxtProfile->JetTblSecID,
  2776. JET_bitSeekEQ
  2777. );
  2778. rc = SceJetJetErrorToSceStatus(JetErr);
  2779. if ( rc == SCESTATUS_SUCCESS ) {
  2780. //
  2781. // find the section ID, retrieve column Name
  2782. //
  2783. if ( Name != NULL ) {
  2784. JetErr = JetRetrieveColumn(
  2785. cxtProfile->JetSessionID,
  2786. cxtProfile->JetTblSecID,
  2787. cxtProfile->JetSecNameID,
  2788. (void *)Name,
  2789. *pNameLen,
  2790. &Actual,
  2791. 0,
  2792. NULL
  2793. );
  2794. *pNameLen = Actual;
  2795. rc = SceJetJetErrorToSceStatus(JetErr);
  2796. }
  2797. }
  2798. }
  2799. return(rc);
  2800. }
  2801. SCESTATUS
  2802. SceJetAddSection(
  2803. IN PSCECONTEXT cxtProfile,
  2804. IN PCWSTR Name,
  2805. OUT DOUBLE *SectionID
  2806. )
  2807. /* ++
  2808. Routine Description:
  2809. Arguments:
  2810. Return Value:
  2811. -- */
  2812. {
  2813. SCESTATUS rc;
  2814. DWORD Len;
  2815. JET_ERR JetErr;
  2816. PWSTR LwrName=NULL;
  2817. if ( cxtProfile == NULL ||
  2818. Name == NULL ||
  2819. SectionID == NULL ) {
  2820. return(SCESTATUS_INVALID_PARAMETER);
  2821. }
  2822. rc = SceJetGetSectionIDByName(
  2823. cxtProfile,
  2824. Name,
  2825. SectionID
  2826. );
  2827. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  2828. //
  2829. // the record is not there. add it in
  2830. // get the next available section ID first.
  2831. //
  2832. Len = wcslen(Name)*sizeof(WCHAR);
  2833. LwrName = (PWSTR)ScepAlloc(0, Len+2);
  2834. if ( LwrName != NULL ) {
  2835. rc = SceJetpGetAvailableSectionID(
  2836. cxtProfile,
  2837. SectionID
  2838. );
  2839. if ( rc == SCESTATUS_SUCCESS ) {
  2840. //
  2841. // add a record to the section table
  2842. //
  2843. JetErr = JetPrepareUpdate(cxtProfile->JetSessionID,
  2844. cxtProfile->JetTblSecID,
  2845. JET_prepInsert
  2846. );
  2847. rc = SceJetJetErrorToSceStatus(JetErr);
  2848. if ( rc == SCESTATUS_SUCCESS ) {
  2849. //
  2850. // set SectionID and name
  2851. //
  2852. JetErr = JetSetColumn(
  2853. cxtProfile->JetSessionID,
  2854. cxtProfile->JetTblSecID,
  2855. cxtProfile->JetSecID,
  2856. (void *)SectionID,
  2857. 8,
  2858. 0, //JET_bitSetOverwriteLV,
  2859. NULL
  2860. );
  2861. rc = SceJetJetErrorToSceStatus(JetErr);
  2862. if ( rc == SCESTATUS_SUCCESS ) {
  2863. //
  2864. // set Name column
  2865. //
  2866. wcscpy(LwrName, Name);
  2867. LwrName = _wcslwr(LwrName);
  2868. JetErr = JetSetColumn(
  2869. cxtProfile->JetSessionID,
  2870. cxtProfile->JetTblSecID,
  2871. cxtProfile->JetSecNameID,
  2872. (void *)LwrName,
  2873. Len,
  2874. 0,
  2875. NULL
  2876. );
  2877. rc = SceJetJetErrorToSceStatus(JetErr);
  2878. }
  2879. if ( rc != SCESTATUS_SUCCESS ) {
  2880. //
  2881. // if setting fails, cancel the prepared record
  2882. //
  2883. JetPrepareUpdate( cxtProfile->JetSessionID,
  2884. cxtProfile->JetTblSecID,
  2885. JET_prepCancel
  2886. );
  2887. } else {
  2888. //
  2889. // Setting columns succeed. Update the record
  2890. //
  2891. JetErr = JetUpdate(cxtProfile->JetSessionID,
  2892. cxtProfile->JetTblSecID,
  2893. NULL,
  2894. 0,
  2895. &Len
  2896. );
  2897. rc = SceJetJetErrorToSceStatus(JetErr);
  2898. }
  2899. }
  2900. }
  2901. ScepFree(LwrName);
  2902. }
  2903. }
  2904. return(rc);
  2905. }
  2906. SCESTATUS
  2907. SceJetDeleteSectionID(
  2908. IN PSCECONTEXT cxtProfile,
  2909. IN DOUBLE SectionID,
  2910. IN PCWSTR Name
  2911. )
  2912. /* ++
  2913. Routine Description:
  2914. This routine deletes a record from the SmTblSection table. If SectionID
  2915. is not 0, the record will be deleted by ID if there is a match on ID.
  2916. Otherwise, the record will be deleted by Name if there is a match on Name.
  2917. Arguments:
  2918. cxtProfile - The profile context handle
  2919. SectionID - The SectionID to delete (if it is not 0)
  2920. Name - The section name to delete (if it is not NULL ).
  2921. Return Value:
  2922. SCESTATUS_SUCCESS
  2923. SCESTATUS_INVALID_PARAMETER
  2924. SCESTATUS_ACCESS_DENIED
  2925. SCESTATUS_OTHER_ERROR
  2926. SCESTATUS from SceJetGetSectionIDByName
  2927. SCESTATUS from SceJetGetSectionNameByID
  2928. -- */
  2929. {
  2930. SCESTATUS rc;
  2931. JET_ERR JetErr;
  2932. if ( cxtProfile == NULL )
  2933. return(SCESTATUS_INVALID_PARAMETER);
  2934. if ( SectionID > (DOUBLE)0 ) {
  2935. //
  2936. // delete by SectionID
  2937. //
  2938. rc = SceJetGetSectionNameByID(
  2939. cxtProfile,
  2940. SectionID,
  2941. NULL,
  2942. NULL
  2943. );
  2944. if ( rc == SCESTATUS_SUCCESS ) {
  2945. // find it
  2946. JetErr = JetDelete(cxtProfile->JetSessionID, cxtProfile->JetTblSecID);
  2947. rc = SceJetJetErrorToSceStatus(JetErr);
  2948. }
  2949. return(rc);
  2950. }
  2951. if ( Name != NULL && wcslen(Name) > 0 ) {
  2952. //
  2953. // delete by Name
  2954. //
  2955. rc = SceJetGetSectionIDByName(
  2956. cxtProfile,
  2957. Name,
  2958. NULL
  2959. );
  2960. if ( rc == SCESTATUS_SUCCESS ) {
  2961. // find it
  2962. JetErr = JetDelete(cxtProfile->JetSessionID, cxtProfile->JetTblSecID);
  2963. rc = SceJetJetErrorToSceStatus(JetErr);
  2964. }
  2965. return(rc);
  2966. }
  2967. return(SCESTATUS_INVALID_PARAMETER);
  2968. }
  2969. //
  2970. // Other private APIs
  2971. //
  2972. JET_ERR
  2973. SceJetpSeek(
  2974. IN PSCESECTION hSection,
  2975. IN PWSTR LinePrefix,
  2976. IN DWORD PrefixLength,
  2977. IN SCEJET_SEEK_FLAG SeekBit,
  2978. IN BOOL bOkNoMatch
  2979. )
  2980. /* ++
  2981. Routine Description:
  2982. This routine seeks to the current key as built with SceJetpMakeKey.
  2983. If there is no records start with the SectionID+LinePrefix, a
  2984. JET_errRecordNotFound is returned. This is similar to exact or partial
  2985. match search.
  2986. There is a 255 bytes limit on Jet engine's index. If SectionID plus
  2987. the line prefix is over this limit, this routine will scroll to the next
  2988. record until find a line starting with SectionID + LinePrefix.
  2989. Arguments:
  2990. hSection - the context handle of the section
  2991. LinePrefix - The prefix for fields to start with
  2992. PrefixLength- The length of the prefix in BYTES
  2993. grbit - The option for JetSeek
  2994. Return Value:
  2995. JET_ERR returned from JetMakeKey,JetSeek,JetRetrieveColumn, JetMove
  2996. -- */
  2997. {
  2998. JET_ERR JetErr;
  2999. INT Result=0;
  3000. JET_GRBIT grbit;
  3001. DWORD Actual;
  3002. //
  3003. // make the key first
  3004. //
  3005. JetErr = SceJetpMakeKey(
  3006. hSection->JetSessionID,
  3007. hSection->JetTableID,
  3008. hSection->SectionID,
  3009. LinePrefix,
  3010. PrefixLength
  3011. );
  3012. if ( JetErr != JET_errSuccess ) {
  3013. return(JetErr);
  3014. }
  3015. //
  3016. // Call Jet engine's JetSeek to take to the first line
  3017. // to start with.
  3018. //
  3019. switch ( SeekBit ) {
  3020. case SCEJET_SEEK_EQ:
  3021. grbit = JET_bitSeekEQ;
  3022. break;
  3023. case SCEJET_SEEK_GT:
  3024. if ( LinePrefix != NULL && PrefixLength > 247 )
  3025. grbit = JET_bitSeekGE;
  3026. else
  3027. grbit = JET_bitSeekGT;
  3028. break;
  3029. default:
  3030. grbit = JET_bitSeekGE;
  3031. }
  3032. JetErr = JetSeek(
  3033. hSection->JetSessionID,
  3034. hSection->JetTableID,
  3035. grbit
  3036. );
  3037. if ( JetErr == JET_errSuccess ||
  3038. JetErr == JET_wrnSeekNotEqual ) {
  3039. if ( LinePrefix != NULL && PrefixLength > 247 ) {
  3040. //
  3041. // info is truncated
  3042. // The current record may be before the actual one
  3043. //
  3044. do {
  3045. //
  3046. // check the current record
  3047. //
  3048. JetErr = SceJetpCompareLine(
  3049. hSection,
  3050. grbit,
  3051. LinePrefix,
  3052. PrefixLength,
  3053. &Result,
  3054. &Actual
  3055. );
  3056. if ( JetErr == JET_errSuccess &&
  3057. ( Result < 0 || (Result == 0 && SeekBit == SCEJET_SEEK_GT) )) {
  3058. //
  3059. // current record's data is less than the prefix, move to next
  3060. //
  3061. JetErr = JetMove(hSection->JetSessionID,
  3062. hSection->JetTableID,
  3063. JET_MoveNext,
  3064. 0
  3065. );
  3066. if ( JetErr == JET_errNoCurrentRecord )
  3067. JetErr = JET_errRecordNotFound;
  3068. }
  3069. } while ( JetErr == JET_errSuccess &&
  3070. ( (Result < 0 && SeekBit != SCEJET_SEEK_EQ) ||
  3071. (Result == 0 && SeekBit == SCEJET_SEEK_GT) ) );
  3072. if ( SeekBit == SCEJET_SEEK_EQ && JetErr == JET_errSuccess &&
  3073. Result == 0 && Actual > PrefixLength ) {
  3074. //
  3075. // no exact match
  3076. //
  3077. return(JET_errRecordNotFound);
  3078. } // for SEEK_GE check, see below
  3079. } else {
  3080. //
  3081. // Prefix is not overlimit. Check the current record only.
  3082. //
  3083. if (SeekBit != SCEJET_SEEK_EQ)
  3084. JetErr = SceJetpCompareLine(
  3085. hSection,
  3086. grbit,
  3087. LinePrefix,
  3088. PrefixLength,
  3089. &Result,
  3090. 0
  3091. );
  3092. }
  3093. if ( JetErr == JET_errSuccess && Result > 0 ) {
  3094. if ( SeekBit == SCEJET_SEEK_EQ ) {
  3095. //
  3096. // Prefix is less than the current line, which is OK if for SEEK_GE and SEEK_GT
  3097. //
  3098. return(JET_errRecordNotFound);
  3099. } else if ( SeekBit == SCEJET_SEEK_GE && LinePrefix && PrefixLength && !bOkNoMatch ) {
  3100. //
  3101. return(JET_errRecordNotFound);
  3102. }
  3103. }
  3104. }
  3105. return(JetErr);
  3106. }
  3107. JET_ERR
  3108. SceJetpCompareLine(
  3109. IN PSCESECTION hSection,
  3110. IN JET_GRBIT grbit,
  3111. IN PWSTR LinePrefix OPTIONAL,
  3112. IN DWORD PrefixLength,
  3113. OUT INT *Result,
  3114. OUT DWORD *ActualLength OPTIONAL
  3115. )
  3116. /* ++
  3117. Routine Description:
  3118. This routine comapre the current line with the SectionID in the section
  3119. handle and name column with LinePrefix if LinePrefix is not NULL. The
  3120. purpose of this routine is to see if the cursor is still on a record
  3121. which has the same sectionID and prefix.
  3122. The comparsion result is output from Result. If JET_errSuccess returns
  3123. and Result < 0, the current record is BEFORE the prefix; If Result = 0,
  3124. the current record has the same key with prefix; If Result > 0, the
  3125. current record is AFTER the prefix. If no more record is available to
  3126. be compared, JET_errRecordNotFound returns. Any other error occurs inside
  3127. the routine is returned.
  3128. Arguments:
  3129. hSection - the section handle
  3130. LinePrefix - The prefix to match
  3131. PrefixLength - The number of BYTES in LinePrefix
  3132. Return Value:
  3133. JET_errSuccess
  3134. JET_errRecordNotFound
  3135. JET_errOutOfMemory
  3136. JET_ERR returned from JetRetrieveColumn
  3137. -- */
  3138. {
  3139. JET_ERR JetErr;
  3140. DOUBLE SectionID;
  3141. DWORD Actual;
  3142. JET_RETINFO RetInfo;
  3143. PWSTR Buffer=NULL;
  3144. // *Result = 0;
  3145. // return(JET_errSuccess);
  3146. //
  3147. // Compare the section first
  3148. //
  3149. JetErr = JetRetrieveColumn(
  3150. hSection->JetSessionID,
  3151. hSection->JetTableID,
  3152. hSection->JetColumnSectionID,
  3153. (void *)&SectionID,
  3154. 8,
  3155. &Actual,
  3156. 0,
  3157. NULL
  3158. );
  3159. if ( JetErr == JET_errNoCurrentRecord )
  3160. return(JET_errRecordNotFound);
  3161. else if ( JetErr != JET_errSuccess )
  3162. return(JetErr);
  3163. if ( hSection->SectionID < SectionID ) {
  3164. *Result = 1;
  3165. // if ( grbit != JET_bitSeekGT )
  3166. return(JET_errRecordNotFound);
  3167. } else if ( hSection->SectionID == SectionID )
  3168. *Result = 0;
  3169. else
  3170. *Result = -1;
  3171. if ( *Result != 0 || grbit == JET_bitSeekGT )
  3172. return(JetErr);
  3173. //
  3174. // check Name column
  3175. //
  3176. if ( LinePrefix != NULL && PrefixLength > 0 ) {
  3177. RetInfo.ibLongValue = 0;
  3178. RetInfo.cbStruct = sizeof(JET_RETINFO);
  3179. RetInfo.itagSequence = 1;
  3180. Buffer = (PWSTR)LocalAlloc(LMEM_ZEROINIT, PrefixLength+2);
  3181. if ( Buffer == NULL )
  3182. return(JET_errOutOfMemory);
  3183. JetErr = JetRetrieveColumn(
  3184. hSection->JetSessionID,
  3185. hSection->JetTableID,
  3186. hSection->JetColumnNameID,
  3187. (void *)Buffer,
  3188. PrefixLength,
  3189. &Actual,
  3190. 0,
  3191. &RetInfo
  3192. );
  3193. if ( JetErr == JET_errNoCurrentRecord )
  3194. JetErr = JET_errRecordNotFound;
  3195. if ( JetErr != JET_errSuccess &&
  3196. JetErr != JET_wrnBufferTruncated ) {
  3197. if ( JetErr > 0 ) {
  3198. // warnings, do not return equal
  3199. JetErr = JET_errSuccess;
  3200. *Result = 1;
  3201. }
  3202. LocalFree(Buffer);
  3203. return(JetErr);
  3204. }
  3205. JetErr = JET_errSuccess;
  3206. //
  3207. // Compare the first PrefixLength bytes.
  3208. //
  3209. *Result = _wcsnicmp(Buffer,
  3210. LinePrefix,
  3211. PrefixLength/sizeof(WCHAR));
  3212. //printf("Compare %ws to %ws for Length %d: Result=%d\n", Buffer, LinePrefix, PrefixLength/2, *Result);
  3213. LocalFree(Buffer);
  3214. if ( ActualLength != NULL )
  3215. *ActualLength = Actual;
  3216. }
  3217. return(JetErr);
  3218. }
  3219. JET_ERR
  3220. SceJetpMakeKey(
  3221. IN JET_SESID SessionID,
  3222. IN JET_TABLEID TableID,
  3223. IN DOUBLE SectionID,
  3224. IN PWSTR LinePrefix,
  3225. IN DWORD PrefixLength
  3226. )
  3227. /* ++
  3228. Routine Description:
  3229. This routine constructs a normalized key value for Seek. It constructs
  3230. the section name in the section context first. Then the LinePrefix is
  3231. added if it is not NULL.
  3232. The scp, sap and smp tables all have one index which is Section+Name.
  3233. Arguments:
  3234. SessionID - the Jet session ID
  3235. TableID - The Jet table ID to work in
  3236. SectionID - The ID in column "SectionID"
  3237. LinePrefix - The prefix for fields to start with
  3238. PrefixLength- The length of the prefix in BYTES
  3239. Return Value:
  3240. JET_ERR from JetMakeKey
  3241. -- */
  3242. {
  3243. JET_ERR JetErr;
  3244. JET_GRBIT grbit;
  3245. if ( LinePrefix == NULL ) {
  3246. grbit = JET_bitNewKey; // | JET_bitStrLimit; having StrLimit set takes you to the next key
  3247. } else {
  3248. grbit = JET_bitNewKey;
  3249. }
  3250. //
  3251. // Add section ID to the key
  3252. //
  3253. JetErr = JetMakeKey(
  3254. SessionID,
  3255. TableID,
  3256. (VOID *)(&SectionID),
  3257. 8,
  3258. grbit
  3259. );
  3260. if ( JetErr != JET_errSuccess )
  3261. return(JetErr);
  3262. //
  3263. // add prefix to the key if it is not NULL
  3264. //
  3265. if ( LinePrefix != NULL ) {
  3266. JetErr = JetMakeKey(
  3267. SessionID,
  3268. TableID,
  3269. (VOID *)LinePrefix,
  3270. PrefixLength,
  3271. JET_bitSubStrLimit
  3272. );
  3273. }
  3274. if ( JetErr == JET_errKeyIsMade ) {
  3275. //
  3276. // When 2 keys are provided, it may return this code, even on success.
  3277. //
  3278. JetErr = JET_errSuccess;
  3279. }
  3280. return(JetErr);
  3281. }
  3282. JET_ERR
  3283. SceJetpBuildUpperLimit(
  3284. IN PSCESECTION hSection,
  3285. IN PWSTR LinePrefix,
  3286. IN DWORD Len,
  3287. IN BOOL bReserveCase
  3288. )
  3289. /* ++
  3290. Function Descripton:
  3291. This routine builts an upper index range based on a section and an
  3292. optional prefix. If prefix is NULL, the upper limit is the next
  3293. available sectionID. If prefix is not NULL, the upper limit is the
  3294. last character 's next character in the key.
  3295. For example, if prefix is a\b\c\d\e\f\g, the upper limit is then
  3296. a\b\c\d\e\f\h. If prefix is over 247 (index limit), e.g.,
  3297. aaa...\b..\c...\d...\e...\f\x\t\y\z
  3298. ^
  3299. |
  3300. the 247th byte.
  3301. then the upper limit is built to aaa...\b..\c...\d...\e...\g
  3302. Arguments:
  3303. hSection - The seciton's handle
  3304. LinePrefix - The prefix
  3305. Len - The number of bytes in the prefix
  3306. Return Value:
  3307. JET_ERR from SceJetpMakeKey, JetSetIndexRange
  3308. -- */
  3309. {
  3310. JET_ERR JetErr;
  3311. DWORD indx;
  3312. WCHAR UpperLimit[128];
  3313. if ( Len == 0 ) {
  3314. // no prefix. The upper limit is the next available section ID
  3315. JetErr = SceJetpMakeKey(
  3316. hSection->JetSessionID,
  3317. hSection->JetTableID,
  3318. hSection->SectionID+(DOUBLE)1,
  3319. NULL,
  3320. 0
  3321. );
  3322. } else {
  3323. memset(UpperLimit, 0, 128*sizeof(WCHAR));
  3324. if ( Len < 247 )
  3325. // prefix is not overlimit.
  3326. // The upper limit is the last character + 1
  3327. indx = Len / sizeof(WCHAR);
  3328. else
  3329. // prefix is overlimit (247)
  3330. // built range on 247 bytes
  3331. indx = 123;
  3332. wcsncpy(UpperLimit, LinePrefix, indx);
  3333. UpperLimit[indx] = L'\0';
  3334. if ( !bReserveCase ) {
  3335. _wcslwr(UpperLimit);
  3336. }
  3337. UpperLimit[indx-1] = (WCHAR) (UpperLimit[indx-1] + 1);
  3338. JetErr = SceJetpMakeKey(
  3339. hSection->JetSessionID,
  3340. hSection->JetTableID,
  3341. hSection->SectionID,
  3342. UpperLimit,
  3343. Len
  3344. );
  3345. }
  3346. if ( JetErr != JET_errSuccess )
  3347. return(JetErr);
  3348. //
  3349. // set upper limit
  3350. //
  3351. JetErr = JetSetIndexRange(
  3352. hSection->JetSessionID,
  3353. hSection->JetTableID,
  3354. JET_bitRangeUpperLimit //| JET_bitRangeInclusive
  3355. );
  3356. return(JetErr);
  3357. }
  3358. SCESTATUS
  3359. SceJetJetErrorToSceStatus(
  3360. IN JET_ERR JetErr
  3361. )
  3362. /* ++
  3363. Routine Description:
  3364. This routine converts error returned from Jet engine (JET_ERR) to SCESTATUS.
  3365. Arguments:
  3366. JetErr - The error returned from Jet engine
  3367. Return Value:
  3368. All available SCESTATUS error codes
  3369. -- */
  3370. {
  3371. SCESTATUS rc;
  3372. switch ( JetErr ) {
  3373. case JET_errSuccess:
  3374. case JET_wrnSeekNotEqual:
  3375. case JET_wrnNoErrorInfo:
  3376. case JET_wrnColumnNull:
  3377. case JET_wrnColumnSetNull:
  3378. case JET_wrnTableEmpty:
  3379. case JET_errAlreadyInitialized:
  3380. rc = SCESTATUS_SUCCESS;
  3381. break;
  3382. case JET_errDatabaseInvalidName:
  3383. rc = SCESTATUS_INVALID_PARAMETER;
  3384. break;
  3385. case JET_errNoCurrentRecord:
  3386. case JET_errRecordNotFound:
  3387. rc = SCESTATUS_RECORD_NOT_FOUND;
  3388. break;
  3389. case JET_errColumnDoesNotFit:
  3390. case JET_errColumnTooBig:
  3391. rc = SCESTATUS_INVALID_DATA;
  3392. break;
  3393. case JET_errDatabaseDuplicate:
  3394. case JET_errTableDuplicate:
  3395. case JET_errColumnDuplicate:
  3396. case JET_errIndexDuplicate:
  3397. case JET_errKeyDuplicate:
  3398. rc = SCESTATUS_OBJECT_EXIST;
  3399. break;
  3400. case JET_wrnBufferTruncated:
  3401. rc = SCESTATUS_BUFFER_TOO_SMALL;
  3402. break;
  3403. case JET_errFileNotFound:
  3404. case JET_errDatabaseNotFound:
  3405. rc = SCESTATUS_PROFILE_NOT_FOUND;
  3406. break;
  3407. case JET_errObjectNotFound:
  3408. case JET_errIndexNotFound:
  3409. case JET_errColumnNotFound:
  3410. case JET_errDatabaseCorrupted:
  3411. rc = SCESTATUS_BAD_FORMAT;
  3412. break;
  3413. case JET_errTooManyOpenDatabases:
  3414. case JET_errTooManyOpenTables:
  3415. case JET_errDiskFull:
  3416. case JET_errOutOfMemory:
  3417. case JET_errVersionStoreOutOfMemory:
  3418. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3419. break;
  3420. case JET_errPermissionDenied:
  3421. case JET_errFileAccessDenied:
  3422. case JET_errTableInUse:
  3423. case JET_errTableLocked:
  3424. case JET_errWriteConflict:
  3425. rc = SCESTATUS_ACCESS_DENIED;
  3426. break;
  3427. case JET_errFeatureNotAvailable:
  3428. case JET_errQueryNotSupported:
  3429. case JET_errSQLLinkNotSupported:
  3430. case JET_errLinkNotSupported:
  3431. case JET_errIllegalOperation:
  3432. rc = SCESTATUS_SERVICE_NOT_SUPPORT;
  3433. break;
  3434. default:
  3435. //printf("JetErr=%d\n", JetErr);
  3436. rc = SCESTATUS_OTHER_ERROR;
  3437. break;
  3438. }
  3439. return(rc);
  3440. }
  3441. SCESTATUS
  3442. SceJetpGetAvailableSectionID(
  3443. IN PSCECONTEXT cxtProfile,
  3444. OUT DOUBLE *SectionID
  3445. )
  3446. /* ++
  3447. Routine Description:
  3448. Arguments:
  3449. cxtProfile - The profile context handle
  3450. SectionID - The output section ID
  3451. Return Value:
  3452. SCESTATUS_SUCCESS
  3453. SCESTATUS_INVALID_PARAMETER
  3454. SCESTATUS_RECORD_NOT_FOUND
  3455. SCESTATUS_BAD_FORMAT
  3456. SCESTATUS_OTHER_ERROR
  3457. -- */
  3458. {
  3459. SCESTATUS rc;
  3460. JET_ERR JetErr;
  3461. DWORD Actual;
  3462. if ( cxtProfile == NULL || SectionID == NULL )
  3463. return(SCESTATUS_INVALID_PARAMETER);
  3464. if ( cxtProfile->JetTblSecID <= 0) {
  3465. //
  3466. // Section table is not opened yet
  3467. //
  3468. rc = SceJetOpenTable(
  3469. cxtProfile,
  3470. "SmTblSection",
  3471. SCEJET_TABLE_SECTION,
  3472. SCEJET_OPEN_READ_ONLY,
  3473. NULL
  3474. );
  3475. if ( rc != SCESTATUS_SUCCESS )
  3476. return(rc);
  3477. }
  3478. *SectionID = (DOUBLE)0;
  3479. //
  3480. // set current index to SecID (the ID)
  3481. //
  3482. JetErr = JetSetCurrentIndex(
  3483. cxtProfile->JetSessionID,
  3484. cxtProfile->JetTblSecID,
  3485. "SecID"
  3486. );
  3487. rc = SceJetJetErrorToSceStatus(JetErr);
  3488. if ( rc != SCESTATUS_SUCCESS )
  3489. return(rc);
  3490. //
  3491. // Move to the last record
  3492. //
  3493. JetErr = JetMove(
  3494. cxtProfile->JetSessionID,
  3495. cxtProfile->JetTblSecID,
  3496. JET_MoveLast,
  3497. 0
  3498. );
  3499. rc = SceJetJetErrorToSceStatus(JetErr);
  3500. if ( rc == SCESTATUS_SUCCESS ) {
  3501. //
  3502. // find the section ID, retrieve column Name
  3503. //
  3504. JetErr = JetRetrieveColumn(
  3505. cxtProfile->JetSessionID,
  3506. cxtProfile->JetTblSecID,
  3507. cxtProfile->JetSecID,
  3508. (void *)SectionID,
  3509. 8,
  3510. &Actual,
  3511. 0,
  3512. NULL
  3513. );
  3514. rc = SceJetJetErrorToSceStatus(JetErr);
  3515. if ( rc == SCESTATUS_SUCCESS ) {
  3516. //
  3517. // The next available ID is current ID + 1
  3518. //
  3519. *SectionID = *SectionID + (DOUBLE)1;
  3520. }
  3521. } else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  3522. *SectionID = (DOUBLE)1;
  3523. rc = SCESTATUS_SUCCESS;
  3524. }
  3525. return(rc);
  3526. }
  3527. SCESTATUS
  3528. SceJetpAddAllSections(
  3529. IN PSCECONTEXT cxtProfile
  3530. )
  3531. /* ++
  3532. Routine Description:
  3533. This routine adds all pre-defined sections into the section table.
  3534. This routine is used when creating the section table.
  3535. Arguments:
  3536. cxtProfile - The profile context
  3537. Return Value:
  3538. SCESTATUS from SceJetAddSection
  3539. -- */
  3540. {
  3541. SCESTATUS rc;
  3542. DOUBLE SectionID;
  3543. rc = SceJetAddSection(
  3544. cxtProfile,
  3545. szSystemAccess,
  3546. &SectionID
  3547. );
  3548. if ( rc != SCESTATUS_SUCCESS )
  3549. return(rc);
  3550. rc = SceJetAddSection(
  3551. cxtProfile,
  3552. szPrivilegeRights,
  3553. &SectionID
  3554. );
  3555. if ( rc != SCESTATUS_SUCCESS )
  3556. return(rc);
  3557. rc = SceJetAddSection(
  3558. cxtProfile,
  3559. szGroupMembership,
  3560. &SectionID
  3561. );
  3562. if ( rc != SCESTATUS_SUCCESS )
  3563. return(rc);
  3564. rc = SceJetAddSection(
  3565. cxtProfile,
  3566. szAccountProfiles,
  3567. &SectionID
  3568. );
  3569. if ( rc != SCESTATUS_SUCCESS )
  3570. return(rc);
  3571. rc = SceJetAddSection(
  3572. cxtProfile,
  3573. szRegistryKeys,
  3574. &SectionID
  3575. );
  3576. if ( rc != SCESTATUS_SUCCESS )
  3577. return(rc);
  3578. rc = SceJetAddSection(
  3579. cxtProfile,
  3580. szFileSecurity,
  3581. &SectionID
  3582. );
  3583. if ( rc != SCESTATUS_SUCCESS )
  3584. return(rc);
  3585. rc = SceJetAddSection(
  3586. cxtProfile,
  3587. szDSSecurity,
  3588. &SectionID
  3589. );
  3590. if ( rc != SCESTATUS_SUCCESS )
  3591. return(rc);
  3592. rc = SceJetAddSection(
  3593. cxtProfile,
  3594. szAuditSystemLog,
  3595. &SectionID
  3596. );
  3597. if ( rc != SCESTATUS_SUCCESS )
  3598. return(rc);
  3599. rc = SceJetAddSection(
  3600. cxtProfile,
  3601. szAuditSecurityLog,
  3602. &SectionID
  3603. );
  3604. if ( rc != SCESTATUS_SUCCESS )
  3605. return(rc);
  3606. rc = SceJetAddSection(
  3607. cxtProfile,
  3608. szAuditApplicationLog,
  3609. &SectionID
  3610. );
  3611. if ( rc != SCESTATUS_SUCCESS )
  3612. return(rc);
  3613. rc = SceJetAddSection(
  3614. cxtProfile,
  3615. szAuditEvent,
  3616. &SectionID
  3617. );
  3618. if ( rc != SCESTATUS_SUCCESS )
  3619. return(rc);
  3620. rc = SceJetAddSection(
  3621. cxtProfile,
  3622. szUserList,
  3623. &SectionID
  3624. );
  3625. if ( rc != SCESTATUS_SUCCESS )
  3626. return(rc);
  3627. rc = SceJetAddSection(
  3628. cxtProfile,
  3629. szKerberosPolicy,
  3630. &SectionID
  3631. );
  3632. if ( rc != SCESTATUS_SUCCESS )
  3633. return(rc);
  3634. rc = SceJetAddSection(
  3635. cxtProfile,
  3636. szServiceGeneral,
  3637. &SectionID
  3638. );
  3639. if ( rc != SCESTATUS_SUCCESS )
  3640. return(rc);
  3641. rc = SceJetAddSection(
  3642. cxtProfile,
  3643. szRegistryValues,
  3644. &SectionID
  3645. );
  3646. return(rc);
  3647. }
  3648. SCESTATUS
  3649. SceJetpConfigJetSystem(
  3650. IN JET_INSTANCE *hinstance
  3651. )
  3652. {
  3653. SCESTATUS rc=SCESTATUS_SUCCESS;
  3654. DWORD Win32rc;
  3655. JET_ERR JetErr;
  3656. DWORD Len;
  3657. PWSTR SysRoot=NULL;
  3658. PWSTR ProfileLocation=NULL;
  3659. CHAR FileName[512];
  3660. PSECURITY_DESCRIPTOR pSD=NULL;
  3661. SECURITY_INFORMATION SeInfo;
  3662. DWORD SDsize;
  3663. //
  3664. // the default Jet working directory is always in %SystemRoot%\security
  3665. // no matter who is logged on.
  3666. // this way allows one jet working directory
  3667. //
  3668. Len = 0;
  3669. Win32rc = ScepGetNTDirectory( &SysRoot, &Len, SCE_FLAG_WINDOWS_DIR );
  3670. if ( Win32rc == NO_ERROR ) {
  3671. if ( SysRoot != NULL ) {
  3672. Len += 9; // profile location
  3673. ProfileLocation = (PWSTR)ScepAlloc( 0, (Len+1)*sizeof(WCHAR));
  3674. if ( ProfileLocation == NULL ) {
  3675. Win32rc = ERROR_NOT_ENOUGH_MEMORY;
  3676. } else {
  3677. swprintf(ProfileLocation, L"%s\\Security", SysRoot );
  3678. ProfileLocation[Len] = L'\0';
  3679. }
  3680. ScepFree(SysRoot);
  3681. } else
  3682. Win32rc = ERROR_INVALID_DATA;
  3683. }
  3684. if ( Win32rc == NO_ERROR ) {
  3685. #ifdef SCEJET_DBG
  3686. wprintf(L"Default location: %s\n", ProfileLocation);
  3687. #endif
  3688. //
  3689. // convert WCHAR into ANSI
  3690. //
  3691. memset(FileName, '\0', 512);
  3692. Win32rc = RtlNtStatusToDosError(
  3693. RtlUnicodeToMultiByteN(
  3694. (PCHAR)FileName,
  3695. 512,
  3696. NULL,
  3697. ProfileLocation,
  3698. Len*sizeof(WCHAR)
  3699. ));
  3700. if ( Win32rc == NO_ERROR ) {
  3701. //
  3702. // a backslash is required by Jet
  3703. //
  3704. strcat(FileName, "\\");
  3705. //
  3706. // set everyone change, admin full control to the directory
  3707. // the directory is created in the function.
  3708. //
  3709. Win32rc = ConvertTextSecurityDescriptor (
  3710. L"D:P(A;CIOI;GRGW;;;WD)(A;CIOI;GA;;;BA)(A;CIOI;GA;;;SY)",
  3711. &pSD,
  3712. &SDsize,
  3713. &SeInfo
  3714. );
  3715. if ( Win32rc == NO_ERROR ) {
  3716. ScepChangeAclRevision(pSD, ACL_REVISION);
  3717. rc = ScepCreateDirectory(
  3718. ProfileLocation,
  3719. TRUE, // a dir name
  3720. pSD // take parent's security setting
  3721. );
  3722. #ifdef SCEJET_DBG
  3723. if ( rc != SCESTATUS_SUCCESS )
  3724. wprintf(L"Cannot create directory %s\n", ProfileLocation );
  3725. #endif
  3726. if ( rc == SCESTATUS_SUCCESS ) {
  3727. __try {
  3728. JetErr = JetSetSystemParameter( hinstance, 0, JET_paramSystemPath, 0, (const char *)FileName );
  3729. rc = SceJetJetErrorToSceStatus(JetErr);
  3730. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3731. //
  3732. // esent is not loaded
  3733. //
  3734. rc = SCESTATUS_MOD_NOT_FOUND;
  3735. }
  3736. }
  3737. if ( rc == SCESTATUS_SUCCESS ) {
  3738. JetErr = JetSetSystemParameter( hinstance, 0, JET_paramTempPath, 0, (const char *)FileName );
  3739. if ( JetErr == JET_errSuccess ) {
  3740. JetErr = JetSetSystemParameter( hinstance, 0, JET_paramLogFilePath, 0, (const char *)FileName );
  3741. if ( JetErr == JET_errSuccess ) {
  3742. JetErr = JetSetSystemParameter( hinstance, 0, JET_paramDatabasePageSize, 4096, NULL );
  3743. }
  3744. }
  3745. rc = SceJetJetErrorToSceStatus(JetErr);
  3746. if ( rc == SCESTATUS_SUCCESS ) {
  3747. //
  3748. // set log size to 1M
  3749. //
  3750. JetSetSystemParameter( hinstance, 0, JET_paramLogFileSize, 1024, NULL );
  3751. //
  3752. // defer the event log to when event log service is available
  3753. // (for example, in NT setup, there is no event log)
  3754. //
  3755. JetSetSystemParameter( hinstance, 0, JET_paramEventLogCache, 128, NULL );
  3756. JetSetSystemParameter( hinstance, 0, JET_paramMaxVerPages, 128, NULL );
  3757. //
  3758. // set minimize = maximum cache size to disable DBA in jet
  3759. // recommended setting for minimum is 4 * number of sessions
  3760. // maximum is up to the app (for performance)
  3761. //
  3762. JetSetSystemParameter( hinstance, 0, JET_paramMaxSessions, 64, NULL );
  3763. //
  3764. // performance is about 10% faster when using cache size 512 than 256
  3765. //
  3766. JetSetSystemParameter( hinstance, 0, JET_paramStartFlushThreshold, 50, NULL ); // sugguested by Exchange
  3767. JetSetSystemParameter( hinstance, 0, JET_paramStopFlushThreshold, 100, NULL ); // suggested by Exchange
  3768. //
  3769. // can't set to 512 because that's Jet's default value
  3770. // jet won't turn off DBA if value is set to 512.
  3771. //
  3772. JetSetSystemParameter( hinstance, 0, JET_paramCacheSizeMax, 496, NULL ); //256
  3773. JetSetSystemParameter( hinstance, 0, JET_paramCacheSizeMin, 496, NULL ); //256
  3774. //
  3775. // other system parameters, such as memory size in beta2
  3776. //
  3777. JetErr = JetSetSystemParameter( hinstance, 0, JET_paramCircularLog, 1, NULL );
  3778. JetErr = JetSetSystemParameter( hinstance, 0, JET_paramNoInformationEvent, 1, NULL );
  3779. }
  3780. }
  3781. ScepFree(pSD);
  3782. }
  3783. }
  3784. ScepFree(ProfileLocation);
  3785. }
  3786. if ( rc == SCESTATUS_SUCCESS ) {
  3787. rc = ScepDosErrorToSceStatus(Win32rc);
  3788. }
  3789. return(rc);
  3790. }
  3791. SCESTATUS
  3792. SceJetGetTimeStamp(
  3793. IN PSCECONTEXT cxtProfile,
  3794. OUT PLARGE_INTEGER ConfigTimeStamp,
  3795. OUT PLARGE_INTEGER AnalyzeTimeStamp
  3796. )
  3797. /* ++
  3798. Routine Description:
  3799. This routine queries the time stamp of last analysis.
  3800. The time stamp is saved in the "SmTblVersion" table.
  3801. Arguments:
  3802. cxtProfile - The profile context
  3803. Return Value:
  3804. SCESTATUS_SUCCESS
  3805. SCESTATUS_BAD_FORMAT
  3806. SCESTATUS_OTHER_ERROR
  3807. SCESTATUS from SceJetOpenTable
  3808. -- */
  3809. {
  3810. SCESTATUS rc=SCESTATUS_SUCCESS;
  3811. DWORD RetLen = 0;
  3812. if (cxtProfile == NULL )
  3813. return(SCESTATUS_INVALID_PARAMETER);
  3814. //
  3815. // Open version table
  3816. //
  3817. if ( ConfigTimeStamp != NULL ) {
  3818. rc = SceJetpGetValueFromVersion(
  3819. cxtProfile,
  3820. "SmTblVersion",
  3821. "ConfigTimeStamp",
  3822. (CHAR*)ConfigTimeStamp, //TimeStamp,
  3823. 8, // 16, // number of bytes
  3824. &RetLen
  3825. );
  3826. if ( rc == SCESTATUS_SUCCESS ||
  3827. rc == SCESTATUS_BUFFER_TOO_SMALL )
  3828. rc = SCESTATUS_SUCCESS;
  3829. if ( RetLen < 8 ) {
  3830. (*ConfigTimeStamp).LowPart = 0;
  3831. (*ConfigTimeStamp).HighPart = 0;
  3832. }
  3833. }
  3834. if ( AnalyzeTimeStamp != NULL ) {
  3835. rc |= SceJetpGetValueFromVersion(
  3836. cxtProfile,
  3837. "SmTblVersion",
  3838. "AnalyzeTimeStamp",
  3839. (CHAR*)AnalyzeTimeStamp, //TimeStamp,
  3840. 8, // 16, // number of bytes
  3841. &RetLen
  3842. );
  3843. if ( rc == SCESTATUS_SUCCESS ||
  3844. rc == SCESTATUS_BUFFER_TOO_SMALL )
  3845. rc = SCESTATUS_SUCCESS;
  3846. if ( RetLen < 8 ) {
  3847. (*AnalyzeTimeStamp).LowPart = 0;
  3848. (*AnalyzeTimeStamp).HighPart = 0;
  3849. }
  3850. }
  3851. return(rc);
  3852. }
  3853. SCESTATUS
  3854. SceJetSetTimeStamp(
  3855. IN PSCECONTEXT cxtProfile,
  3856. IN BOOL Flag,
  3857. IN LARGE_INTEGER NewTimeStamp
  3858. )
  3859. /* ++
  3860. Routine Description:
  3861. This routine sets the time stamp (LARGE_INTEGER) of a analysis.
  3862. The time stamp is saved in the "SmTblVersion" table.
  3863. Arguments:
  3864. cxtProfile - The profile context
  3865. Flag - indicates analyze or configure
  3866. Flag = TRUE - AnalyzeTimeStamp
  3867. Flag = FALSE - ConfigTimeStamp
  3868. NewTimeStamp - the new time stamp of a analysis
  3869. Return Value:
  3870. SCESTATUS_SUCCESS
  3871. SCESTATUS_BAD_FORMAT
  3872. SCESTATUS_OTHER_ERROR
  3873. SCESTATUS from SceJetOpenTable
  3874. -- */
  3875. {
  3876. SCESTATUS rc;
  3877. #ifdef SCE_JETDBG
  3878. CHAR CharTimeStamp[17];
  3879. sprintf(CharTimeStamp, "%08x%08x", NewTimeStamp.HighPart, NewTimeStamp.LowPart);
  3880. CharTimeStamp[16] = '\0';
  3881. printf("New time stamp is %s\n", CharTimeStamp);
  3882. #endif
  3883. if ( cxtProfile == NULL ) {
  3884. return(SCESTATUS_INVALID_PARAMETER);
  3885. }
  3886. //
  3887. // set
  3888. //
  3889. if ( Flag ) {
  3890. rc = SceJetSetValueInVersion(
  3891. cxtProfile,
  3892. "SmTblVersion",
  3893. "AnalyzeTimeStamp",
  3894. (PWSTR)(&NewTimeStamp), //(PWSTR)CharTimeStamp,
  3895. 8, // 16, // number of bytes
  3896. JET_prepReplace
  3897. );
  3898. } else {
  3899. rc = SceJetSetValueInVersion(
  3900. cxtProfile,
  3901. "SmTblVersion",
  3902. "ConfigTimeStamp",
  3903. (PWSTR)(&NewTimeStamp), //(PWSTR)CharTimeStamp,
  3904. 8, // 16, // number of bytes
  3905. JET_prepReplace
  3906. );
  3907. }
  3908. return(rc);
  3909. }
  3910. SCESTATUS
  3911. SceJetGetDescription(
  3912. IN PSCECONTEXT cxtProfile,
  3913. OUT PWSTR *Description
  3914. )
  3915. /* ++
  3916. Routine Description:
  3917. This routine queries the profile description from the "SmTblVersion" table.
  3918. Arguments:
  3919. cxtProfile - The profile context
  3920. Description - The description buffer
  3921. Return Value:
  3922. SCESTATUS_SUCCESS
  3923. SCESTATUS_BAD_FORMAT
  3924. SCESTATUS_OTHER_ERROR
  3925. SCESTATUS from SceJetOpenTable
  3926. -- */
  3927. {
  3928. SCESTATUS rc;
  3929. DWORD RetLen = 0;
  3930. if ( cxtProfile == NULL || Description == NULL ) {
  3931. return(SCESTATUS_INVALID_PARAMETER);
  3932. }
  3933. //
  3934. // Open version table
  3935. //
  3936. rc = SceJetpGetValueFromVersion(
  3937. cxtProfile,
  3938. "SmTblVersion",
  3939. "ProfileDescription",
  3940. NULL,
  3941. 0, // number of bytes
  3942. &RetLen
  3943. );
  3944. if ( rc == SCESTATUS_BUFFER_TOO_SMALL ) {
  3945. *Description = (PWSTR)ScepAlloc( LPTR, RetLen+2 );
  3946. if ( *Description == NULL )
  3947. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  3948. rc = SceJetpGetValueFromVersion(
  3949. cxtProfile,
  3950. "SmTblVersion",
  3951. "ProfileDescription",
  3952. (LPSTR)(*Description),
  3953. RetLen, // number of bytes
  3954. &RetLen
  3955. );
  3956. if ( rc != SCESTATUS_SUCCESS ) {
  3957. ScepFree( *Description );
  3958. *Description = NULL;
  3959. }
  3960. }
  3961. return(rc);
  3962. }
  3963. SCESTATUS
  3964. SceJetpGetValueFromVersion(
  3965. IN PSCECONTEXT cxtProfile,
  3966. IN LPSTR TableName,
  3967. IN LPSTR ColumnName,
  3968. OUT LPSTR Value OPTIONAL,
  3969. IN DWORD ValueLen, // number of bytes
  3970. OUT PDWORD pRetLen
  3971. )
  3972. {
  3973. SCESTATUS rc;
  3974. JET_TABLEID TableID;
  3975. JET_ERR JetErr;
  3976. JET_COLUMNDEF ColumnDef;
  3977. //
  3978. // Open version table
  3979. //
  3980. rc = SceJetOpenTable(
  3981. cxtProfile,
  3982. TableName,
  3983. SCEJET_TABLE_VERSION,
  3984. SCEJET_OPEN_READ_ONLY,
  3985. &TableID
  3986. );
  3987. if ( rc == SCESTATUS_SUCCESS ) {
  3988. //
  3989. // go to the first record
  3990. //
  3991. JetErr = JetMove(cxtProfile->JetSessionID,
  3992. TableID,
  3993. JET_MoveFirst,
  3994. 0
  3995. );
  3996. rc = SceJetJetErrorToSceStatus(JetErr);
  3997. if ( rc == SCESTATUS_SUCCESS) {
  3998. //
  3999. // get column ID for "Version"
  4000. //
  4001. JetErr = JetGetTableColumnInfo(
  4002. cxtProfile->JetSessionID,
  4003. TableID,
  4004. ColumnName,
  4005. (VOID *)&ColumnDef,
  4006. sizeof(JET_COLUMNDEF),
  4007. 0
  4008. );
  4009. rc = SceJetJetErrorToSceStatus(JetErr);
  4010. if ( rc == SCESTATUS_SUCCESS ) {
  4011. //
  4012. // retrieve the column
  4013. //
  4014. JetErr = JetRetrieveColumn(
  4015. cxtProfile->JetSessionID,
  4016. TableID,
  4017. ColumnDef.columnid,
  4018. (void *)Value,
  4019. ValueLen,
  4020. pRetLen,
  4021. 0,
  4022. NULL
  4023. );
  4024. rc = SceJetJetErrorToSceStatus(JetErr);
  4025. }
  4026. }
  4027. JetCloseTable(cxtProfile->JetSessionID, TableID);
  4028. }
  4029. return(rc);
  4030. }
  4031. SCESTATUS
  4032. SceJetSetValueInVersion(
  4033. IN PSCECONTEXT cxtProfile,
  4034. IN LPSTR TableName,
  4035. IN LPSTR ColumnName,
  4036. IN PWSTR Value,
  4037. IN DWORD ValueLen, // number of bytes
  4038. IN DWORD Prep
  4039. )
  4040. {
  4041. SCESTATUS rc;
  4042. DWORD Len;
  4043. JET_TABLEID TableID;
  4044. JET_ERR JetErr;
  4045. JET_COLUMNDEF ColumnDef;
  4046. if ( cxtProfile == NULL || TableName == NULL || ColumnName == NULL ) {
  4047. return(SCESTATUS_INVALID_PARAMETER);
  4048. }
  4049. //
  4050. // Open version table
  4051. //
  4052. rc = SceJetOpenTable(
  4053. cxtProfile,
  4054. TableName,
  4055. SCEJET_TABLE_VERSION,
  4056. SCEJET_OPEN_READ_WRITE, // read and write
  4057. &TableID
  4058. );
  4059. if ( rc == SCESTATUS_SUCCESS ) {
  4060. //
  4061. // go to the first record
  4062. //
  4063. JetErr = JetMove(cxtProfile->JetSessionID,
  4064. TableID,
  4065. JET_MoveFirst,
  4066. 0
  4067. );
  4068. rc = SceJetJetErrorToSceStatus(JetErr);
  4069. if ( rc == SCESTATUS_SUCCESS) {
  4070. //
  4071. // get column ID for "Version"
  4072. //
  4073. JetErr = JetGetTableColumnInfo(
  4074. cxtProfile->JetSessionID,
  4075. TableID,
  4076. ColumnName,
  4077. (VOID *)&ColumnDef,
  4078. sizeof(JET_COLUMNDEF),
  4079. 0
  4080. );
  4081. rc = SceJetJetErrorToSceStatus(JetErr);
  4082. if ( rc == SCESTATUS_SUCCESS ) {
  4083. JetErr = JetPrepareUpdate(cxtProfile->JetSessionID,
  4084. TableID,
  4085. Prep
  4086. );
  4087. rc = SceJetJetErrorToSceStatus(JetErr);
  4088. if ( rc == SCESTATUS_SUCCESS ) {
  4089. //
  4090. // set value
  4091. //
  4092. JetErr = JetSetColumn(
  4093. cxtProfile->JetSessionID,
  4094. TableID,
  4095. ColumnDef.columnid,
  4096. (void *)Value,
  4097. ValueLen,
  4098. 0, //JET_bitSetOverwriteLV,
  4099. NULL
  4100. );
  4101. rc = SceJetJetErrorToSceStatus(JetErr);
  4102. if ( rc != SCESTATUS_SUCCESS ) {
  4103. //
  4104. // if setting fails, cancel the prepared record
  4105. //
  4106. JetPrepareUpdate( cxtProfile->JetSessionID,
  4107. TableID,
  4108. JET_prepCancel
  4109. );
  4110. } else {
  4111. //
  4112. // Setting columns succeed. Update the record
  4113. //
  4114. JetErr = JetUpdate( cxtProfile->JetSessionID,
  4115. TableID,
  4116. NULL,
  4117. 0,
  4118. &Len
  4119. );
  4120. rc = SceJetJetErrorToSceStatus(JetErr);
  4121. }
  4122. }
  4123. }
  4124. }
  4125. JetCloseTable(cxtProfile->JetSessionID, TableID);
  4126. }
  4127. return(rc);
  4128. }
  4129. SCESTATUS
  4130. SceJetSeek(
  4131. IN PSCESECTION hSection,
  4132. IN PWSTR LinePrefix,
  4133. IN DWORD PrefixLength,
  4134. IN SCEJET_SEEK_FLAG SeekBit
  4135. )
  4136. {
  4137. PWSTR LwrPrefix=NULL;
  4138. SCESTATUS rc;
  4139. SCEJET_SEEK_FLAG NewSeekBit;
  4140. if ( hSection == NULL ) {
  4141. return(SCESTATUS_INVALID_PARAMETER);
  4142. }
  4143. if ( LinePrefix != NULL && SeekBit > SCEJET_SEEK_GE ) {
  4144. //
  4145. // do lowercase search
  4146. //
  4147. LwrPrefix = (PWSTR)ScepAlloc(0, PrefixLength+sizeof(WCHAR));
  4148. if ( LwrPrefix == NULL ) {
  4149. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  4150. } else {
  4151. wcscpy(LwrPrefix, LinePrefix);
  4152. LwrPrefix = _wcslwr(LwrPrefix);
  4153. switch ( SeekBit ) {
  4154. case SCEJET_SEEK_GT_NO_CASE:
  4155. NewSeekBit = SCEJET_SEEK_GT;
  4156. break;
  4157. case SCEJET_SEEK_EQ_NO_CASE:
  4158. NewSeekBit = SCEJET_SEEK_EQ;
  4159. break;
  4160. default:
  4161. NewSeekBit = SCEJET_SEEK_GE;
  4162. break;
  4163. }
  4164. rc = SceJetJetErrorToSceStatus(
  4165. SceJetpSeek(
  4166. hSection,
  4167. LwrPrefix,
  4168. PrefixLength,
  4169. NewSeekBit,
  4170. (SeekBit == SCEJET_SEEK_GE_DONT_CARE)
  4171. ));
  4172. ScepFree(LwrPrefix);
  4173. }
  4174. } else {
  4175. //
  4176. // do case sensitive search, or NULL search
  4177. //
  4178. rc = SceJetJetErrorToSceStatus(
  4179. SceJetpSeek(
  4180. hSection,
  4181. LinePrefix,
  4182. PrefixLength,
  4183. SeekBit,
  4184. FALSE
  4185. ));
  4186. }
  4187. return(rc);
  4188. }
  4189. SCESTATUS
  4190. SceJetMoveNext(
  4191. IN PSCESECTION hSection
  4192. )
  4193. {
  4194. JET_ERR JetErr;
  4195. INT Result;
  4196. if ( hSection == NULL ) {
  4197. return(SCESTATUS_INVALID_PARAMETER);
  4198. }
  4199. //
  4200. // skip deleted records
  4201. //
  4202. do {
  4203. JetErr = JetMove(hSection->JetSessionID,
  4204. hSection->JetTableID,
  4205. JET_MoveNext,
  4206. 0
  4207. );
  4208. if ( JetErr == JET_errSuccess ) {
  4209. // compare section ID
  4210. JetErr = SceJetpCompareLine(
  4211. hSection,
  4212. JET_bitSeekGE,
  4213. NULL,
  4214. 0,
  4215. &Result,
  4216. NULL
  4217. );
  4218. if ( JetErr == JET_errSuccess && Result != 0 )
  4219. JetErr = JET_errRecordNotFound;
  4220. }
  4221. } while ( JetErr == JET_errRecordDeleted );
  4222. return(SceJetJetErrorToSceStatus(JetErr));
  4223. }
  4224. /*
  4225. SCESTATUS
  4226. SceJetRenameLine(
  4227. IN PSCESECTION hSection,
  4228. IN PWSTR Name,
  4229. IN PWSTR NewName,
  4230. IN BOOL bReserveCase
  4231. )
  4232. {
  4233. PWSTR LwrName=NULL;
  4234. DWORD Len;
  4235. JET_ERR JetErr;
  4236. JET_SETINFO SetInfo;
  4237. if ( !hSection || !Name || !NewName ) {
  4238. return(SCESTATUS_INVALID_PARAMETER);
  4239. }
  4240. Len = wcslen(NewName)*sizeof(WCHAR);
  4241. if ( Len <= 0 ) {
  4242. return(SCESTATUS_INVALID_PARAMETER);
  4243. }
  4244. if ( bReserveCase ) {
  4245. LwrName = NewName;
  4246. } else {
  4247. //
  4248. // lower cased
  4249. //
  4250. LwrName = (PWSTR)ScepAlloc(0, Len+2);
  4251. if ( LwrName == NULL ) {
  4252. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  4253. }
  4254. wcscpy(LwrName, NewName);
  4255. LwrName = _wcslwr(LwrName);
  4256. }
  4257. SetInfo.cbStruct = sizeof(JET_SETINFO);
  4258. SetInfo.itagSequence = 1;
  4259. SetInfo.ibLongValue = 0;
  4260. //
  4261. // check to see if the same key name already exists
  4262. //
  4263. JetErr = SceJetSeek(
  4264. hSection,
  4265. Name,
  4266. wcslen(Name)*sizeof(WCHAR),
  4267. SCEJET_SEEK_EQ_NO_CASE
  4268. );
  4269. if ( JetErr == JET_errSuccess ) {
  4270. //
  4271. // find a match. overwrite the value
  4272. //
  4273. JetErr = JetBeginTransaction(hSection->JetSessionID);
  4274. if ( JetErr == JET_errSuccess ) {
  4275. JetErr = JetPrepareUpdate(hSection->JetSessionID,
  4276. hSection->JetTableID,
  4277. JET_prepReplace
  4278. );
  4279. if ( JetErr == JET_errSuccess ) {
  4280. //
  4281. // set the new key in "Name" column
  4282. //
  4283. JetErr = JetSetColumn(
  4284. hSection->JetSessionID,
  4285. hSection->JetTableID,
  4286. hSection->JetColumnNameID,
  4287. (void *)LwrName,
  4288. Len,
  4289. JET_bitSetOverwriteLV,
  4290. &SetInfo
  4291. );
  4292. }
  4293. if ( JET_errSuccess == JetErr ) {
  4294. //
  4295. // commit the transaction
  4296. //
  4297. JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
  4298. } else {
  4299. //
  4300. // rollback the transaction
  4301. //
  4302. JetRollback(hSection->JetSessionID,0);
  4303. }
  4304. JetPrepareUpdate(hSection->JetSessionID,
  4305. hSection->JetTableID,
  4306. JET_prepCancel
  4307. );
  4308. }
  4309. }
  4310. if ( LwrName != NewName ) {
  4311. ScepFree(LwrName);
  4312. }
  4313. return( SceJetJetErrorToSceStatus(JetErr) );
  4314. }
  4315. */
  4316. SCESTATUS
  4317. SceJetRenameLine(
  4318. IN PSCESECTION hSection,
  4319. IN PWSTR Name,
  4320. IN PWSTR NewName,
  4321. IN BOOL bReserveCase
  4322. )
  4323. {
  4324. PWSTR Value=NULL;
  4325. DWORD ValueLen;
  4326. SCESTATUS rc;
  4327. JET_ERR JetErr;
  4328. if ( !hSection || !Name || !NewName ) {
  4329. return(SCESTATUS_INVALID_PARAMETER);
  4330. }
  4331. rc = SceJetGetValue(
  4332. hSection,
  4333. SCEJET_EXACT_MATCH_NO_CASE,
  4334. Name,
  4335. NULL,
  4336. 0,
  4337. NULL,
  4338. NULL,
  4339. 0,
  4340. &ValueLen
  4341. );
  4342. if ( SCESTATUS_SUCCESS == rc ) {
  4343. //
  4344. // continue only when this record is found.
  4345. //
  4346. if ( ValueLen ) {
  4347. Value = (PWSTR)ScepAlloc(0, ValueLen+2);
  4348. if ( Value ) {
  4349. rc = SceJetGetValue(
  4350. hSection,
  4351. SCEJET_CURRENT,
  4352. NULL,
  4353. NULL,
  4354. 0,
  4355. NULL,
  4356. Value,
  4357. ValueLen,
  4358. &ValueLen
  4359. );
  4360. } else
  4361. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4362. }
  4363. if ( SCESTATUS_SUCCESS == rc ) {
  4364. JetErr = JetBeginTransaction(hSection->JetSessionID);
  4365. if ( JetErr == JET_errSuccess ) {
  4366. //
  4367. // now delete this line
  4368. //
  4369. rc = SceJetDelete(hSection, NULL, FALSE, SCEJET_DELETE_LINE);
  4370. if ( SCESTATUS_SUCCESS == rc ) {
  4371. //
  4372. // add the new line in.
  4373. //
  4374. rc = SceJetSetLine(
  4375. hSection,
  4376. NewName,
  4377. bReserveCase,
  4378. Value,
  4379. ValueLen,
  4380. 0
  4381. );
  4382. }
  4383. if ( SCESTATUS_SUCCESS == rc ) {
  4384. //
  4385. // commit the transaction
  4386. //
  4387. JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
  4388. } else {
  4389. //
  4390. // rollback the transaction
  4391. //
  4392. JetRollback(hSection->JetSessionID,0);
  4393. }
  4394. } else
  4395. rc = SceJetJetErrorToSceStatus(JetErr);
  4396. }
  4397. }
  4398. return( rc );
  4399. }
  4400. //////////////////////////////////////////////////////////////
  4401. //
  4402. // Helpers
  4403. //
  4404. //////////////////////////////////////////////////////////////
  4405. VOID
  4406. SceJetInitializeData()
  4407. //
  4408. // only be called during server initialization code
  4409. //
  4410. {
  4411. JetInited = FALSE;
  4412. JetInstance = 0;
  4413. }
  4414. SCESTATUS
  4415. SceJetInitialize(
  4416. OUT JET_ERR *pJetErr OPTIONAL
  4417. )
  4418. /*
  4419. Routine Description:
  4420. Initialize jet engine for sce server
  4421. Arguments:
  4422. None
  4423. Return Value:
  4424. SCESTATUS
  4425. */
  4426. {
  4427. SCESTATUS rc=SCESTATUS_SUCCESS;
  4428. JET_ERR JetErr=0;
  4429. //
  4430. // cancel any pending timer queue
  4431. //
  4432. ScepServerCancelTimer();
  4433. EnterCriticalSection(&JetSync);
  4434. if ( !JetInited ) {
  4435. //
  4436. // set system configuration for Jet engine
  4437. //
  4438. rc = SceJetpConfigJetSystem( &JetInstance);
  4439. if ( SCESTATUS_SUCCESS == rc ) {
  4440. //
  4441. // initialize jet engine
  4442. //
  4443. __try {
  4444. JetErr = JetInit(&JetInstance);
  4445. JetInitAttempted = TRUE;
  4446. rc = SceJetJetErrorToSceStatus(JetErr);
  4447. if ( JetErr == JET_errSuccess ) {
  4448. JetInited = TRUE;
  4449. //
  4450. // if failed to initialize Jet writer (for backup/restore)
  4451. // don't fail the engine
  4452. //
  4453. } else {
  4454. //
  4455. // this will happen only if jet cannot recover the
  4456. // database by itself (JetInit() claims to attempt recovery only)
  4457. // repair might help - so only spew out a message advising the user
  4458. //
  4459. // map error so setup/policy propagation clients
  4460. // can log events
  4461. //
  4462. // if ( SCE_JET_CORRUPTION_ERROR(JetErr) ) {
  4463. rc = SCESTATUS_JET_DATABASE_ERROR;
  4464. ScepLogOutput3(0, ERROR_DATABASE_FAILURE, SCEDLL_ERROR_RECOVER_DB );
  4465. // }
  4466. JetInstance = 0;
  4467. }
  4468. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4469. //
  4470. // for some reason, esent is not loaded
  4471. //
  4472. rc = SCESTATUS_MOD_NOT_FOUND;
  4473. JetInstance = 0;
  4474. }
  4475. } else {
  4476. JetInstance = 0;
  4477. }
  4478. }
  4479. LeaveCriticalSection(&JetSync);
  4480. if ( pJetErr ) *pJetErr = JetErr;
  4481. return(rc);
  4482. }
  4483. SCESTATUS
  4484. SceJetTerminate(BOOL bCleanVs)
  4485. /*
  4486. Routine Description:
  4487. Terminate jet engine
  4488. Arguments:
  4489. bCleanVs - if to clean up the version store completely
  4490. Return Value:
  4491. SCESTATUS
  4492. */
  4493. {
  4494. EnterCriticalSection(&JetSync);
  4495. //
  4496. // destroy the jet backup/restore writer
  4497. //
  4498. if ( JetInited || JetInstance ) {
  4499. if ( bCleanVs ) {
  4500. //
  4501. // clean up version store
  4502. //
  4503. JetTerm2(JetInstance, JET_bitTermComplete);
  4504. } else {
  4505. //
  4506. // do not clean up version store
  4507. //
  4508. JetTerm(JetInstance);
  4509. }
  4510. JetInstance = 0;
  4511. JetInited = FALSE;
  4512. }
  4513. LeaveCriticalSection(&JetSync);
  4514. return(SCESTATUS_SUCCESS);
  4515. }
  4516. SCESTATUS
  4517. SceJetTerminateNoCritical(BOOL bCleanVs)
  4518. /*
  4519. Routine Description:
  4520. Terminate jet engine, NOT critical sectioned!!!
  4521. Arguments:
  4522. bCleanVs - if to clean up the version store completely
  4523. Return Value:
  4524. SCESTATUS
  4525. */
  4526. {
  4527. //
  4528. // the critical section is entered outside of this function
  4529. //
  4530. // destroy the jet backup/restore writer
  4531. //
  4532. if ( JetInited || JetInstance ) {
  4533. if ( bCleanVs ) {
  4534. //
  4535. // clean up version store
  4536. //
  4537. JetTerm2(JetInstance, JET_bitTermComplete);
  4538. } else {
  4539. //
  4540. // do not clean up version store
  4541. //
  4542. JetTerm(JetInstance);
  4543. }
  4544. JetInstance = 0;
  4545. JetInited = FALSE;
  4546. }
  4547. return(SCESTATUS_SUCCESS);
  4548. }
  4549. SCESTATUS
  4550. SceJetStartTransaction(
  4551. IN PSCECONTEXT cxtProfile
  4552. )
  4553. /*
  4554. Routine Description:
  4555. Start a transaction on the session
  4556. Arguments:
  4557. cxtProfile - the database context
  4558. Return Value:
  4559. SCESTATUS
  4560. */
  4561. {
  4562. JET_ERR JetErr;
  4563. if ( cxtProfile == NULL )
  4564. return(SCESTATUS_INVALID_PARAMETER);
  4565. JetErr = JetBeginTransaction( cxtProfile->JetSessionID);
  4566. return( SceJetJetErrorToSceStatus(JetErr));
  4567. }
  4568. SCESTATUS
  4569. SceJetCommitTransaction(
  4570. IN PSCECONTEXT cxtProfile,
  4571. IN JET_GRBIT grbit
  4572. )
  4573. /*
  4574. Routine Description:
  4575. Commit a transaction on the session
  4576. Arguments:
  4577. cxtProfile - the database context
  4578. grbit - flag for the commission
  4579. Return Value:
  4580. SCESTATUS
  4581. */
  4582. {
  4583. JET_ERR JetErr;
  4584. if ( cxtProfile == NULL )
  4585. return(SCESTATUS_INVALID_PARAMETER);
  4586. JetErr = JetCommitTransaction(cxtProfile->JetSessionID, grbit );
  4587. return( SceJetJetErrorToSceStatus(JetErr) );
  4588. }
  4589. SCESTATUS
  4590. SceJetRollback(
  4591. IN PSCECONTEXT cxtProfile,
  4592. IN JET_GRBIT grbit
  4593. )
  4594. /*
  4595. Routine Description:
  4596. Rollback a transaction on the session
  4597. Arguments:
  4598. cxtProfile - the database context
  4599. grbit - the flag for transaction rollback
  4600. Return Value:
  4601. SCESTATUS
  4602. */
  4603. {
  4604. JET_ERR JetErr;
  4605. if ( cxtProfile == NULL )
  4606. return(SCESTATUS_SUCCESS);
  4607. __try {
  4608. JetErr = JetRollback(cxtProfile->JetSessionID, grbit);
  4609. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4610. JetErr = JET_errOutOfMemory;
  4611. }
  4612. return( SceJetJetErrorToSceStatus(JetErr) );
  4613. }
  4614. BOOL
  4615. SceJetDeleteJetFiles(
  4616. IN PWSTR DbFileName
  4617. )
  4618. {
  4619. TCHAR TempFileName[MAX_PATH];
  4620. PWSTR SysRoot=NULL;
  4621. DWORD SysLen;
  4622. DWORD rc;
  4623. intptr_t hFile;
  4624. struct _wfinddata_t fInfo;
  4625. BOOL bRet = FALSE;
  4626. EnterCriticalSection(&JetSync);
  4627. if ( JetInitAttempted == TRUE &&
  4628. JetInited == FALSE ) {
  4629. SysLen = 0;
  4630. rc = ScepGetNTDirectory( &SysRoot, &SysLen, SCE_FLAG_WINDOWS_DIR );
  4631. if ( rc == NO_ERROR && SysRoot != NULL ) {
  4632. swprintf(TempFileName, L"%s\\Security\\res1.log\0", SysRoot);
  4633. TempFileName[MAX_PATH-1] = L'\0';
  4634. DeleteFile(TempFileName);
  4635. swprintf(TempFileName, L"%s\\Security\\res2.log\0", SysRoot);
  4636. TempFileName[MAX_PATH-1] = L'\0';
  4637. DeleteFile(TempFileName);
  4638. //
  4639. // delete edb files
  4640. //
  4641. swprintf(TempFileName, L"%s\\Security\\edb*.*\0", SysRoot);
  4642. TempFileName[MAX_PATH-1] = L'\0';
  4643. hFile = _wfindfirst(TempFileName, &fInfo);
  4644. if ( hFile != -1 ) {
  4645. do {
  4646. swprintf(TempFileName, L"%s\\Security\\%s\0", SysRoot, fInfo.name);
  4647. TempFileName[MAX_PATH-1] = L'\0';
  4648. DeleteFile(TempFileName);
  4649. } while ( _wfindnext(hFile, &fInfo) == 0 );
  4650. _findclose(hFile);
  4651. }
  4652. //
  4653. // delete temp files
  4654. //
  4655. swprintf(TempFileName, L"%s\\Security\\tmp*.edb\0", SysRoot);
  4656. TempFileName[MAX_PATH-1] = L'\0';
  4657. hFile = _wfindfirst(TempFileName, &fInfo);
  4658. if ( hFile != -1 ) {
  4659. do {
  4660. swprintf(TempFileName, L"%s\\Security\\%s\0", SysRoot, fInfo.name);
  4661. TempFileName[MAX_PATH-1] = L'\0';
  4662. DeleteFile(TempFileName);
  4663. } while ( _wfindnext(hFile, &fInfo) == 0 );
  4664. _findclose(hFile);
  4665. }
  4666. ScepFree(SysRoot);
  4667. //
  4668. // delete the database file if it's passed in.
  4669. //
  4670. if ( DbFileName ) {
  4671. DeleteFile(DbFileName);
  4672. }
  4673. bRet = TRUE;
  4674. }
  4675. }
  4676. LeaveCriticalSection(&JetSync);
  4677. return(bRet);
  4678. }
  4679. SCESTATUS
  4680. SceJetSetCurrentLine(
  4681. IN PSCESECTION hSection,
  4682. IN PWSTR Value,
  4683. IN DWORD ValueLen
  4684. )
  4685. /* ++
  4686. Fucntion Description:
  4687. This routine writes the Value to the current line in section (hSection).
  4688. Make sure the cursor is on the right line before calling this API
  4689. Arguments:
  4690. hSection - The context handle of the section
  4691. Value - The info set to Column "Value"
  4692. ValueLen - The size of the value field.
  4693. Return Value:
  4694. SCESTATUS_SUCCESS
  4695. SCESTATUS_INVALID_PARAMETER
  4696. SCESTATUS_OTHER_ERROR
  4697. SCESTATUS_ACCESS_DENIED
  4698. SCESTATUS_DATA_OVERFLOW
  4699. -- */
  4700. {
  4701. JET_ERR JetErr;
  4702. DWORD Len;
  4703. SCESTATUS rc;
  4704. DWORD prep;
  4705. JET_SETINFO SetInfo;
  4706. if ( hSection == NULL ||
  4707. Value == NULL ) {
  4708. return(SCESTATUS_INVALID_PARAMETER);
  4709. }
  4710. SetInfo.cbStruct = sizeof(JET_SETINFO);
  4711. SetInfo.itagSequence = 1;
  4712. SetInfo.ibLongValue = 0;
  4713. prep = JET_prepReplace;
  4714. JetErr = JetBeginTransaction(hSection->JetSessionID);
  4715. if ( JetErr == JET_errSuccess ) {
  4716. JetErr = JetPrepareUpdate(hSection->JetSessionID,
  4717. hSection->JetTableID,
  4718. prep
  4719. );
  4720. if ( JetErr != JET_errSuccess ) {
  4721. //
  4722. // rollback the transaction
  4723. //
  4724. JetRollback(hSection->JetSessionID,0);
  4725. }
  4726. }
  4727. if ( JetErr != JET_errSuccess)
  4728. return(SceJetJetErrorToSceStatus(JetErr));
  4729. //
  4730. // set value column
  4731. //
  4732. JetErr = JetSetColumn(
  4733. hSection->JetSessionID,
  4734. hSection->JetTableID,
  4735. hSection->JetColumnValueID,
  4736. (void *)Value,
  4737. ValueLen,
  4738. 0, //JET_bitSetOverwriteLV,
  4739. &SetInfo
  4740. );
  4741. rc = SceJetJetErrorToSceStatus(JetErr);
  4742. if ( JetErr == JET_errSuccess ) {
  4743. //
  4744. // Setting columns succeed. Update the record
  4745. //
  4746. JetErr = JetUpdate(hSection->JetSessionID,
  4747. hSection->JetTableID,
  4748. NULL,
  4749. 0,
  4750. &Len
  4751. );
  4752. } else {
  4753. goto CleanUp;
  4754. }
  4755. if ( rc == SCESTATUS_SUCCESS )
  4756. JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
  4757. CleanUp:
  4758. if ( rc != SCESTATUS_SUCCESS ) {
  4759. //
  4760. // if setting fails, cancel the prepared record
  4761. //
  4762. JetPrepareUpdate(hSection->JetSessionID,
  4763. hSection->JetTableID,
  4764. JET_prepCancel
  4765. );
  4766. //
  4767. // Rollback the transaction
  4768. //
  4769. JetRollback(hSection->JetSessionID,0);
  4770. }
  4771. return(rc);
  4772. }
  4773. BOOL
  4774. ScepIsValidContext(
  4775. PSCECONTEXT context
  4776. )
  4777. {
  4778. if ( context == NULL ) {
  4779. return FALSE;
  4780. }
  4781. __try {
  4782. if ( (context->Type & 0xFFFFFF02L) == 0xFFFFFF02L ) {
  4783. return TRUE;
  4784. } else {
  4785. return FALSE;
  4786. }
  4787. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4788. return FALSE;
  4789. }
  4790. }
  4791. LONG
  4792. SceJetGetGpoIDByName(
  4793. IN PSCECONTEXT cxtProfile,
  4794. IN PWSTR szGpoName,
  4795. IN BOOL bAdd
  4796. )
  4797. /*
  4798. Routine Description:
  4799. Search for a GPO by name in the GPO table. If bAdd is TRUE and the GPO name
  4800. is not found, it will be added to the GPO table
  4801. Arguments:
  4802. cxtProfile - the database handle
  4803. szGpoName - the GPO name
  4804. bAdd - TRUE to add the GPO name to the GPO table if it's not found
  4805. Return Value:
  4806. The GPO ID. If -1 is returned, GetLastError to get the SCE error code.
  4807. */
  4808. {
  4809. SCESTATUS rc;
  4810. JET_ERR JetErr;
  4811. DWORD Actual;
  4812. PWSTR LwrName=NULL;
  4813. DWORD Len;
  4814. if ( cxtProfile == NULL || szGpoName == NULL ||
  4815. szGpoName[0] == L'\0' ) {
  4816. SetLastError(SCESTATUS_INVALID_PARAMETER);
  4817. return (-1);
  4818. }
  4819. JET_TABLEID TableID;
  4820. rc = SceJetOpenTable(
  4821. cxtProfile,
  4822. "SmTblGpo",
  4823. SCEJET_TABLE_GPO,
  4824. bAdd ? SCEJET_OPEN_READ_WRITE : SCEJET_OPEN_READ_ONLY,
  4825. &TableID
  4826. );
  4827. if ( rc != SCESTATUS_SUCCESS ) {
  4828. SetLastError(rc);
  4829. return(-1);
  4830. }
  4831. JET_COLUMNDEF ColumnDef;
  4832. LONG GpoID = 0;
  4833. JetErr = JetGetTableColumnInfo(
  4834. cxtProfile->JetSessionID,
  4835. TableID,
  4836. "GpoID",
  4837. (VOID *)&ColumnDef,
  4838. sizeof(JET_COLUMNDEF),
  4839. JET_ColInfo
  4840. );
  4841. if ( JET_errSuccess == JetErr ) {
  4842. //
  4843. // set current index to SectionKey (the name)
  4844. //
  4845. JetErr = JetSetCurrentIndex(
  4846. cxtProfile->JetSessionID,
  4847. TableID,
  4848. "GpoName"
  4849. );
  4850. }
  4851. rc = SceJetJetErrorToSceStatus(JetErr);
  4852. if ( rc == SCESTATUS_SUCCESS ) {
  4853. //
  4854. // search for the name
  4855. //
  4856. Len = wcslen(szGpoName);
  4857. LwrName = (PWSTR)ScepAlloc(0, (Len+1)*sizeof(WCHAR));
  4858. if ( LwrName != NULL ) {
  4859. wcscpy(LwrName, szGpoName);
  4860. LwrName = _wcslwr(LwrName);
  4861. JetErr = JetMakeKey(
  4862. cxtProfile->JetSessionID,
  4863. TableID,
  4864. (VOID *)LwrName,
  4865. Len*sizeof(WCHAR),
  4866. JET_bitNewKey
  4867. );
  4868. if ( JetErr == JET_errKeyIsMade ) {
  4869. //
  4870. // Only one key is needed, it may return this code, even on success.
  4871. //
  4872. JetErr = JET_errSuccess;
  4873. }
  4874. rc = SceJetJetErrorToSceStatus(JetErr);
  4875. if ( rc == SCESTATUS_SUCCESS ) {
  4876. JetErr = JetSeek(
  4877. cxtProfile->JetSessionID,
  4878. TableID,
  4879. JET_bitSeekEQ
  4880. );
  4881. rc = SceJetJetErrorToSceStatus(JetErr);
  4882. if ( rc == SCESTATUS_SUCCESS ) {
  4883. //
  4884. // find the Gpo name, retrieve gpo id
  4885. //
  4886. JetErr = JetRetrieveColumn(
  4887. cxtProfile->JetSessionID,
  4888. TableID,
  4889. ColumnDef.columnid,
  4890. (void *)&GpoID,
  4891. 4,
  4892. &Actual,
  4893. 0,
  4894. NULL
  4895. );
  4896. rc = SceJetJetErrorToSceStatus(JetErr);
  4897. } else if ( SCESTATUS_RECORD_NOT_FOUND == rc ) {
  4898. GpoID = 0;
  4899. rc = SCESTATUS_SUCCESS;
  4900. if ( bAdd ) {
  4901. //
  4902. // if not found and add is requested
  4903. //
  4904. rc = SceJetpAddGpo(cxtProfile,
  4905. TableID,
  4906. ColumnDef.columnid,
  4907. LwrName,
  4908. &GpoID
  4909. );
  4910. }
  4911. }
  4912. }
  4913. ScepFree(LwrName);
  4914. } else
  4915. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4916. }
  4917. JetCloseTable( cxtProfile->JetSessionID, TableID );
  4918. if ( rc != SCESTATUS_SUCCESS ) {
  4919. SetLastError(rc);
  4920. GpoID = -1;
  4921. }
  4922. return(GpoID);
  4923. }
  4924. SCESTATUS
  4925. SceJetGetGpoNameByID(
  4926. IN PSCECONTEXT cxtProfile,
  4927. IN LONG GpoID,
  4928. OUT PWSTR Name OPTIONAL,
  4929. IN OUT LPDWORD pNameLen,
  4930. OUT PWSTR DisplayName OPTIONAL,
  4931. IN OUT LPDWORD pDispNameLen
  4932. )
  4933. /* ++
  4934. Routine Description:
  4935. This routine retrieve the GPO name for the ID in the GPO table.
  4936. If Name is NULL, this routine really does a seek by ID. The cursor will
  4937. be on the record if there is a successful match.
  4938. Arguments:
  4939. cxtProfile - The profile context handle
  4940. GpoID - The GPO ID looking for
  4941. Name - The optional output buffer for section name
  4942. pNameLen - The name buffer's length
  4943. Return Value:
  4944. SCESTATUS_SUCCESS
  4945. SCESTATUS_INVALID_PARAMETER
  4946. SCESTATUS_RECORD_NOT_FOUND
  4947. SCESTATUS_BAD_FORMAT
  4948. SCESTATUS_OTHER_ERROR
  4949. -- */
  4950. {
  4951. SCESTATUS rc;
  4952. JET_ERR JetErr;
  4953. DWORD Actual;
  4954. if ( cxtProfile == NULL ||
  4955. ( pDispNameLen == NULL && pNameLen == NULL) ) {
  4956. return(SCESTATUS_INVALID_PARAMETER);
  4957. }
  4958. if ( GpoID <= 0 ) {
  4959. return(SCESTATUS_RECORD_NOT_FOUND);
  4960. }
  4961. //
  4962. // reset buffers
  4963. //
  4964. if ( Name == NULL && pNameLen ) {
  4965. *pNameLen = 0;
  4966. }
  4967. if ( DisplayName == NULL && pDispNameLen ) {
  4968. *pDispNameLen = 0;
  4969. }
  4970. JET_TABLEID TableID=0;
  4971. //
  4972. // Open GPO table
  4973. //
  4974. rc = SceJetOpenTable(
  4975. cxtProfile,
  4976. "SmTblGpo",
  4977. SCEJET_TABLE_GPO,
  4978. SCEJET_OPEN_READ_ONLY,
  4979. &TableID
  4980. );
  4981. if ( rc != SCESTATUS_SUCCESS )
  4982. return(rc);
  4983. //
  4984. // set current index to SecID (the ID)
  4985. //
  4986. JetErr = JetSetCurrentIndex(
  4987. cxtProfile->JetSessionID,
  4988. TableID,
  4989. "SectionKey"
  4990. );
  4991. rc = SceJetJetErrorToSceStatus(JetErr);
  4992. if ( rc == SCESTATUS_SUCCESS ) {
  4993. JetErr = JetMakeKey(
  4994. cxtProfile->JetSessionID,
  4995. TableID,
  4996. (void *)(&GpoID),
  4997. 4,
  4998. JET_bitNewKey
  4999. );
  5000. if ( JetErr == JET_errKeyIsMade ) {
  5001. //
  5002. // Only one key is needed, it may return this code, even on success.
  5003. //
  5004. JetErr = JET_errSuccess;
  5005. }
  5006. rc = SceJetJetErrorToSceStatus(JetErr);
  5007. if ( rc == SCESTATUS_SUCCESS ) {
  5008. JetErr = JetSeek(
  5009. cxtProfile->JetSessionID,
  5010. TableID,
  5011. JET_bitSeekEQ
  5012. );
  5013. rc = SceJetJetErrorToSceStatus(JetErr);
  5014. if ( rc == SCESTATUS_SUCCESS ) {
  5015. //
  5016. // find the GPO ID, retrieve column Name if requested
  5017. //
  5018. if ( pNameLen != NULL ) {
  5019. JET_COLUMNDEF ColumnDef;
  5020. JetErr = JetGetTableColumnInfo(
  5021. cxtProfile->JetSessionID,
  5022. TableID,
  5023. "Name",
  5024. (VOID *)&ColumnDef,
  5025. sizeof(JET_COLUMNDEF),
  5026. JET_ColInfo
  5027. );
  5028. rc = SceJetJetErrorToSceStatus(JetErr);
  5029. if ( SCESTATUS_SUCCESS == rc ) {
  5030. JetErr = JetRetrieveColumn(
  5031. cxtProfile->JetSessionID,
  5032. TableID,
  5033. ColumnDef.columnid,
  5034. (void *)Name,
  5035. *pNameLen,
  5036. &Actual,
  5037. 0,
  5038. NULL
  5039. );
  5040. *pNameLen = Actual;
  5041. }
  5042. rc = SceJetJetErrorToSceStatus(JetErr);
  5043. }
  5044. //
  5045. // retrieve column DisplayName if requested
  5046. //
  5047. if ( ( SCESTATUS_SUCCESS == rc) &&
  5048. ( pDispNameLen != NULL) ) {
  5049. JET_COLUMNDEF ColumnDef;
  5050. JetErr = JetGetTableColumnInfo(
  5051. cxtProfile->JetSessionID,
  5052. TableID,
  5053. "DisplayName",
  5054. (VOID *)&ColumnDef,
  5055. sizeof(JET_COLUMNDEF),
  5056. JET_ColInfo
  5057. );
  5058. rc = SceJetJetErrorToSceStatus(JetErr);
  5059. if ( SCESTATUS_SUCCESS == rc ) {
  5060. JetErr = JetRetrieveColumn(
  5061. cxtProfile->JetSessionID,
  5062. TableID,
  5063. ColumnDef.columnid,
  5064. (void *)DisplayName,
  5065. *pDispNameLen,
  5066. &Actual,
  5067. 0,
  5068. NULL
  5069. );
  5070. *pDispNameLen = Actual;
  5071. }
  5072. rc = SceJetJetErrorToSceStatus(JetErr);
  5073. }
  5074. }
  5075. }
  5076. }
  5077. JetCloseTable( cxtProfile->JetSessionID, TableID);
  5078. return(rc);
  5079. }
  5080. SCESTATUS
  5081. SceJetpAddGpo(
  5082. IN PSCECONTEXT cxtProfile,
  5083. IN JET_TABLEID TableID,
  5084. IN JET_COLUMNID GpoIDColumnID,
  5085. IN PCWSTR Name,
  5086. OUT LONG *pGpoID
  5087. )
  5088. /* ++
  5089. Routine Description:
  5090. Arguments:
  5091. Return Value:
  5092. -- */
  5093. {
  5094. SCESTATUS rc;
  5095. JET_ERR JetErr;
  5096. DWORD Len;
  5097. if ( cxtProfile == NULL ||
  5098. Name == NULL ||
  5099. pGpoID == NULL ) {
  5100. return(SCESTATUS_INVALID_PARAMETER);
  5101. }
  5102. *pGpoID = 0;
  5103. //
  5104. // get the next available GPO ID first.
  5105. // set current index to the ID
  5106. //
  5107. JetErr = JetSetCurrentIndex(
  5108. cxtProfile->JetSessionID,
  5109. TableID,
  5110. "SectionKey"
  5111. );
  5112. rc = SceJetJetErrorToSceStatus(JetErr);
  5113. if ( rc != SCESTATUS_SUCCESS )
  5114. return(rc);
  5115. //
  5116. // Move to the last record
  5117. //
  5118. JetErr = JetMove(
  5119. cxtProfile->JetSessionID,
  5120. TableID,
  5121. JET_MoveLast,
  5122. 0
  5123. );
  5124. rc = SceJetJetErrorToSceStatus(JetErr);
  5125. if ( rc == SCESTATUS_SUCCESS ) {
  5126. //
  5127. // find the GPO ID, retrieve column Name
  5128. //
  5129. JetErr = JetRetrieveColumn(
  5130. cxtProfile->JetSessionID,
  5131. TableID,
  5132. GpoIDColumnID,
  5133. (void *)pGpoID,
  5134. 4,
  5135. &Len,
  5136. 0,
  5137. NULL
  5138. );
  5139. rc = SceJetJetErrorToSceStatus(JetErr);
  5140. if ( rc == SCESTATUS_SUCCESS ) {
  5141. //
  5142. // The next available ID is current ID + 1
  5143. //
  5144. *pGpoID = *pGpoID + 1;
  5145. }
  5146. } else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  5147. *pGpoID = 1;
  5148. rc = SCESTATUS_SUCCESS;
  5149. }
  5150. if ( rc == SCESTATUS_SUCCESS ) {
  5151. //
  5152. // add a record to the GPO table
  5153. //
  5154. JetErr = JetPrepareUpdate(cxtProfile->JetSessionID,
  5155. TableID,
  5156. JET_prepInsert
  5157. );
  5158. rc = SceJetJetErrorToSceStatus(JetErr);
  5159. if ( rc == SCESTATUS_SUCCESS ) {
  5160. //
  5161. // set GpoID
  5162. //
  5163. JetErr = JetSetColumn(
  5164. cxtProfile->JetSessionID,
  5165. TableID,
  5166. GpoIDColumnID,
  5167. (void *)pGpoID,
  5168. 4,
  5169. 0, //JET_bitSetOverwriteLV,
  5170. NULL
  5171. );
  5172. rc = SceJetJetErrorToSceStatus(JetErr);
  5173. if ( rc == SCESTATUS_SUCCESS ) {
  5174. //
  5175. // set Name column
  5176. //
  5177. JET_COLUMNDEF ColumnDef;
  5178. JetErr = JetGetTableColumnInfo(
  5179. cxtProfile->JetSessionID,
  5180. TableID,
  5181. "Name",
  5182. (VOID *)&ColumnDef,
  5183. sizeof(JET_COLUMNDEF),
  5184. JET_ColInfo
  5185. );
  5186. rc = SceJetJetErrorToSceStatus(JetErr);
  5187. if ( SCESTATUS_SUCCESS == rc ) {
  5188. Len = wcslen(Name)*sizeof(WCHAR);
  5189. JetErr = JetSetColumn(
  5190. cxtProfile->JetSessionID,
  5191. TableID,
  5192. ColumnDef.columnid,
  5193. (void *)Name,
  5194. Len,
  5195. 0,
  5196. NULL
  5197. );
  5198. rc = SceJetJetErrorToSceStatus(JetErr);
  5199. }
  5200. }
  5201. if ( rc != SCESTATUS_SUCCESS ) {
  5202. //
  5203. // if setting fails, cancel the prepared record
  5204. //
  5205. JetPrepareUpdate( cxtProfile->JetSessionID,
  5206. TableID,
  5207. JET_prepCancel
  5208. );
  5209. } else {
  5210. //
  5211. // Setting columns succeed. Update the record
  5212. //
  5213. JetErr = JetUpdate(cxtProfile->JetSessionID,
  5214. TableID,
  5215. NULL,
  5216. 0,
  5217. &Len
  5218. );
  5219. rc = SceJetJetErrorToSceStatus(JetErr);
  5220. }
  5221. }
  5222. }
  5223. return(rc);
  5224. }
  5225. //
  5226. // request the GPO ID (if there is any) for the object
  5227. //
  5228. SCESTATUS
  5229. SceJetGetGpoID(
  5230. IN PSCESECTION hSection,
  5231. IN PWSTR ObjectName,
  5232. IN JET_COLUMNID JetColGpoID OPTIONAL,
  5233. OUT LONG *pGpoID
  5234. )
  5235. {
  5236. if ( hSection == NULL || ObjectName == NULL || pGpoID == NULL ) {
  5237. return(SCESTATUS_INVALID_PARAMETER);
  5238. }
  5239. SCESTATUS rc;
  5240. *pGpoID = 0;
  5241. JET_COLUMNID ColGpoID = 0;
  5242. if ( JetColGpoID == 0 ) {
  5243. ColGpoID = hSection->JetColumnGpoID;
  5244. } else {
  5245. ColGpoID = JetColGpoID;
  5246. }
  5247. if ( ColGpoID > 0 ) {
  5248. rc = SceJetSeek(
  5249. hSection,
  5250. ObjectName,
  5251. wcslen(ObjectName)*sizeof(WCHAR),
  5252. SCEJET_SEEK_EQ_NO_CASE
  5253. );
  5254. if ( rc == SCESTATUS_SUCCESS ) {
  5255. DWORD Actual;
  5256. JET_ERR JetErr;
  5257. JetErr = JetRetrieveColumn(
  5258. hSection->JetSessionID,
  5259. hSection->JetTableID,
  5260. ColGpoID,
  5261. (void *)pGpoID,
  5262. 4,
  5263. &Actual,
  5264. 0,
  5265. NULL
  5266. );
  5267. if ( JET_errSuccess != JetErr ) {
  5268. //
  5269. // if the column is nil (no value), it will return warning
  5270. // but the buffer pGpoID is trashed
  5271. //
  5272. *pGpoID = 0;
  5273. }
  5274. rc = SceJetJetErrorToSceStatus(JetErr);
  5275. }
  5276. } else {
  5277. rc = SCESTATUS_RECORD_NOT_FOUND;
  5278. }
  5279. return rc;
  5280. }