System.Data.SQLite
Check-in [77a0e66f10]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Refactor native library pre-loading code to be more flexible.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | refactorNativeLibraryPreLoader
Files: files | file ages | folders
SHA1: 77a0e66f105534c8cc6109de764b6403e9d12530
User & Date: mistachkin 2013-12-26 04:01:18
Context
2013-12-26
23:48
More work-in-progress on refactoring the native library pre-loader. check-in: 60011bd9e5 user: mistachkin tags: refactorNativeLibraryPreLoader
04:01
Refactor native library pre-loading code to be more flexible. check-in: 77a0e66f10 user: mistachkin tags: refactorNativeLibraryPreLoader
00:57
Fix HTML entity escaping in the environment variable documentation page. check-in: 2f18d24bcc user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to System.Data.SQLite/SQLiteConnection.cs.

1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
      int n;
      SortedList<string, string> ls = new SortedList<string, string>(StringComparer.OrdinalIgnoreCase);

      // First split into semi-colon delimited values.
      string error = null;
      string[] arParts;

#if !PLATFORM_COMPACTFRAMEWORK
      if (Environment.GetEnvironmentVariable("No_SQLiteConnectionNewParser") != null)
          arParts = SQLiteConvert.Split(s, ';');
      else
#endif
          arParts = SQLiteConvert.NewSplit(s, ';', true, ref error);

      if (arParts == null)
      {
          throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
              "Invalid ConnectionString format, cannot parse: {0}", (error != null) ?
              error : "could not split connection string into properties"));







<
|


<







1619
1620
1621
1622
1623
1624
1625

1626
1627
1628

1629
1630
1631
1632
1633
1634
1635
      int n;
      SortedList<string, string> ls = new SortedList<string, string>(StringComparer.OrdinalIgnoreCase);

      // First split into semi-colon delimited values.
      string error = null;
      string[] arParts;


      if (UnsafeNativeMethods.GetVariableValue("No_SQLiteConnectionNewParser") != null)
          arParts = SQLiteConvert.Split(s, ';');
      else

          arParts = SQLiteConvert.NewSplit(s, ';', true, ref error);

      if (arParts == null)
      {
          throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
              "Invalid ConnectionString format, cannot parse: {0}", (error != null) ?
              error : "could not split connection string into properties"));

Changes to System.Data.SQLite/SQLiteFunction.cs.

653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
      try
      {
#if !PLATFORM_COMPACTFRAMEWORK
        //
        // NOTE: If the "No_SQLiteFunctions" environment variable is set,
        //       skip all our special code and simply return.
        //
        if (Environment.GetEnvironmentVariable("No_SQLiteFunctions") != null)
          return;

        SQLiteFunctionAttribute at;
        System.Reflection.Assembly[] arAssemblies = System.AppDomain.CurrentDomain.GetAssemblies();
        int w = arAssemblies.Length;
        System.Reflection.AssemblyName sqlite = System.Reflection.Assembly.GetExecutingAssembly().GetName();








|







653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
      try
      {
#if !PLATFORM_COMPACTFRAMEWORK
        //
        // NOTE: If the "No_SQLiteFunctions" environment variable is set,
        //       skip all our special code and simply return.
        //
        if (UnsafeNativeMethods.GetVariableValue("No_SQLiteFunctions") != null)
          return;

        SQLiteFunctionAttribute at;
        System.Reflection.Assembly[] arAssemblies = System.AppDomain.CurrentDomain.GetAssemblies();
        int w = arAssemblies.Length;
        System.Reflection.AssemblyName sqlite = System.Reflection.Assembly.GetExecutingAssembly().GetName();

Changes to System.Data.SQLite/SQLiteLog.cs.

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
            //         is loaded per-process and has only one logging callback,
            //         not one per-AppDomain, which it knows nothing about),
            //         prevent all non-default AppDomains from registering a
            //         log handler unless the "Force_SQLiteLog" environment
            //         variable is used to manually override this safety check.
            //
            if (!AppDomain.CurrentDomain.IsDefaultAppDomain() &&
                Environment.GetEnvironmentVariable("Force_SQLiteLog") == null)
            {
                return;
            }
#endif

            lock (syncRoot)
            {







|







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
            //         is loaded per-process and has only one logging callback,
            //         not one per-AppDomain, which it knows nothing about),
            //         prevent all non-default AppDomains from registering a
            //         log handler unless the "Force_SQLiteLog" environment
            //         variable is used to manually override this safety check.
            //
            if (!AppDomain.CurrentDomain.IsDefaultAppDomain() &&
                UnsafeNativeMethods.GetVariableValue("Force_SQLiteLog") == null)
            {
                return;
            }
#endif

            lock (syncRoot)
            {

Changes to System.Data.SQLite/UnsafeNativeMethods.cs.

25
26
27
28
29
30
31


32
33
34
35
36
37
38
..
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84





85
86
87
88
89
90
91
...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
...
244
245
246
247
248
249
250
































































































































































































251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278
279
280
281

282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306


307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324


325
326
327
328
329
330
331
...
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392



393
394
395
396
397
398
399
...
415
416
417
418
419
420
421



422
423
424
425
426
427
428

429
430
431
432





433
434

435
436
437



438
439
440
441
442
443
444
...
454
455
456
457
458
459
460

461
462
463
464
465
466
467
468
469
470
471
472


473
474
475
476
477
478
479
...
528
529
530
531
532
533
534
535

536
537
538
539
540
541
542
...
602
603
604
605
606
607
608



609
610
611
612
613
614
615
616

617
618





619
620
621
622
623
624
625
...
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
....
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
....
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
....
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
....
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
....
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
....
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
#endif

  using System.Runtime.InteropServices;

#if !PLATFORM_COMPACTFRAMEWORK || COUNT_HANDLE
  using System.Threading;
#endif



#if !PLATFORM_COMPACTFRAMEWORK && !DEBUG
  [SuppressUnmanagedCodeSecurity]
#endif
  internal static class UnsafeNativeMethods
  {
      #region Critical Handle Counts (Debug Build Only)
................................................................................
#if SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK

      //
      // NOTE: Only compile in the native library pre-load code if the feature
      //       has been enabled for this build.
      //
#if PRELOAD_NATIVE_LIBRARY
#if !PLATFORM_COMPACTFRAMEWORK
      /// <summary>
      /// The name of the environment variable containing the processor
      /// architecture of the current process.
      /// </summary>
      private static readonly string PROCESSOR_ARCHITECTURE =
          "PROCESSOR_ARCHITECTURE";
#endif

      /////////////////////////////////////////////////////////////////////////

      private static readonly string DllFileExtension = ".dll";






      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// This is the P/Invoke method that wraps the native Win32 LoadLibrary
      /// function.  See the MSDN documentation for full details on what it
      /// does.
      /// </summary>
................................................................................
      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Attempts to initialize this class by pre-loading the native SQLite
      /// library for the processor architecture of the current process.
      /// </summary>
      internal static void Initialize()
      {
#if !PLATFORM_COMPACTFRAMEWORK
          //
          // NOTE: If the "No_PreLoadSQLite" environment variable is set (to
          //       anything), skip all our special code and simply return.
          //
          if (Environment.GetEnvironmentVariable("No_PreLoadSQLite") != null)
              return;
#endif

          lock (staticSyncRoot)
          {
              //
              // TODO: Make sure this list is updated if the supported
              //       processor architecture names and/or platform names
              //       changes.
................................................................................
              if (_SQLiteModule == IntPtr.Zero)
                  _SQLiteModule = PreLoadSQLiteDll(null, null);
          }
      }

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
































































































































































































      /// Queries and returns the base directory of the current application
      /// domain.
      /// </summary>
      /// <returns>
      /// The base directory for the current application domain -OR- null if it
      /// cannot be determined.
      /// </returns>
      private static string GetBaseDirectory()
      {
#if !PLATFORM_COMPACTFRAMEWORK
          //
          // NOTE: If the "PreLoadSQLite_BaseDirectory" environment variable
          //       is set, use it verbatim for the base directory.
          //
          string directory = Environment.GetEnvironmentVariable(
              "PreLoadSQLite_BaseDirectory");

          if (directory != null)
              return directory;


          //
          // NOTE: If the "PreLoadSQLite_UseAssemblyDirectory" environment
          //       variable is set (to anything), attempt to use the directory
          //       containing the currently executing assembly (i.e.
          //       System.Data.SQLite) intsead of the application domain base
          //       directory.
          //
          if (Environment.GetEnvironmentVariable(
                "PreLoadSQLite_UseAssemblyDirectory") != null)
          {
              try

              {
                  Assembly assembly = Assembly.GetExecutingAssembly();

                  if (assembly != null)
                  {
                      directory = Path.GetDirectoryName(assembly.Location);

                      if (!String.IsNullOrEmpty(directory))
                          return directory;
                  }
              }
              catch
              {
                  // do nothing.
              }
          }

          //
          // NOTE: Otherwise, fallback on using the base directory of the
          //       current application domain.
          //
          return AppDomain.CurrentDomain.BaseDirectory;
#else
          Assembly assembly = Assembly.GetExecutingAssembly();



          if (assembly == null)
              return null;

          AssemblyName assemblyName = assembly.GetName();

          if (assemblyName == null)
              return null;

          try
          {
              return Path.GetDirectoryName(assemblyName.CodeBase);
          }
          catch
          {
              // do nothing.
          }

          return null;


#endif
      }

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Determines if the dynamic link library file name requires a suffix
      /// and adds it if necessary.
................................................................................
      /// </summary>
      /// <returns>
      /// The processor architecture of the current process -OR- null if it
      /// cannot be determined.
      /// </returns>
      private static string GetProcessorArchitecture()
      {
#if !PLATFORM_COMPACTFRAMEWORK
          //
          // NOTE: If the "PreLoadSQLite_ProcessorArchitecture" environment
          //       variable is set, use it verbatim for the current processor
          //       architecture.
          //
          string processorArchitecture = Environment.GetEnvironmentVariable(
              "PreLoadSQLite_ProcessorArchitecture");

          if (processorArchitecture != null)
              return processorArchitecture;

          //
          // BUGBUG: Will this always be reliable?
          //
          processorArchitecture = Environment.GetEnvironmentVariable(
              PROCESSOR_ARCHITECTURE);




          //
          // HACK: Check for an "impossible" situation.  If the pointer size
          //       is 32-bits, the processor architecture cannot be "AMD64".
          //       In that case, we are almost certainly hitting a bug in the
          //       operating system and/or Visual Studio that causes the
          //       PROCESSOR_ARCHITECTURE environment variable to contain the
          //       wrong value in some circumstances.  Please refer to ticket
................................................................................
              // NOTE: We know that operating systems that return "AMD64" as
              //       the processor architecture are actually a superset of
              //       the "x86" processor architecture; therefore, return
              //       "x86" when the pointer size is 32-bits.
              //
              processorArchitecture = "x86";




              //
              // NOTE: Show that we hit a fairly unusual situation (i.e. the
              //       "wrong" processor architecture was detected).
              //
#if !NET_COMPACT_20 && TRACE_PRELOAD
              Trace.WriteLine(String.Format(
                  CultureInfo.CurrentCulture,

                  "Detected {0}-bit pointer size with processor architecture " +
                  "\"{1}\", using processor architecture \"{2}\" instead...",
                  IntPtr.Size * 8 /* bits */, savedProcessorArchitecture,
                  processorArchitecture));





#endif
          }


          return processorArchitecture;
#else



          //
          // NOTE: On the .NET Compact Framework, attempt to use the native
          //       Win32 API function (via P/Invoke) that can provide us with
          //       the processor architecture.
          //
          try
          {
................................................................................
              //       the structure.
              //
              GetSystemInfo(out systemInfo);

              //
              // NOTE: Return the processor architecture value as a string.
              //

              return systemInfo.wProcessorArchitecture.ToString();
          }
          catch
          {
              // do nothing.
          }

          //
          // NOTE: Upon failure, return an empty string.
          //
          return String.Empty;
#endif


      }

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Given the processor architecture, returns the name of the platform.
      /// </summary>
      /// <param name="processorArchitecture">
................................................................................
      /// </returns>
      private static IntPtr PreLoadSQLiteDll(
          string directory,
          string processorArchitecture
          )
      {
          //
          // NOTE: If the specified base directory is null, use the default.

          //
          if (directory == null)
              directory = GetBaseDirectory();

          //
          // NOTE: If we failed to query the base directory, stop now.
          //
................................................................................
              // NOTE: If the file does not exist, skip trying to load it.
              //
              if (!File.Exists(fileName))
                  return IntPtr.Zero;
          }

          try



          {
              //
              // NOTE: Show exactly where we are trying to load the native
              //       SQLite library from.
              //
#if !NET_COMPACT_20 && TRACE_PRELOAD
              Trace.WriteLine(String.Format(
                  CultureInfo.CurrentCulture,

                  "Trying to load native SQLite library \"{0}\"...",
                  fileName));





#endif

              //
              // NOTE: Attempt to load the native library.  This will either
              //       return a valid native module handle, return IntPtr.Zero,
              //       or throw an exception.
              //
................................................................................
          {
#if !NET_COMPACT_20 && TRACE_PRELOAD
              try
              {
                  //
                  // NOTE: First, grab the last Win32 error number.
                  //
                  int lastError = Marshal.GetLastWin32Error();

                  //
                  // NOTE: Show where we failed to load the native SQLite
                  //       library from along with the Win32 error code and
                  //       exception information.
                  //
                  Trace.WriteLine(String.Format(
                      CultureInfo.CurrentCulture,
                      "Failed to load native SQLite library \"{0}\" " +
                      "(getLastError = {1}): {2}",
                      fileName, lastError, e)); /* throw */
              }
              catch
              {
                  // do nothing.
              }
#endif
................................................................................
                    SQLiteBase.CloseConnection(this, localHandle);
#endif

#if !NET_COMPACT_20 && TRACE_HANDLE
                try
                {
                    Trace.WriteLine(String.Format(
                        "CloseConnection: {0}", localHandle));
                }
                catch
                {
                }
#endif
#else
                lock (syncRoot)
................................................................................
#endif
            {
#if !NET_COMPACT_20 && TRACE_HANDLE
                try
                {
                    Trace.WriteLine(String.Format(
                        "CloseConnection: {0}, exception: {1}",
                        handle, e));
                }
                catch
                {
                }
#endif
            }
            finally
................................................................................
                if (localHandle != IntPtr.Zero)
                    SQLiteBase.FinalizeStatement(cnn, localHandle);

#if !NET_COMPACT_20 && TRACE_HANDLE
                try
                {
                    Trace.WriteLine(String.Format(
                        "FinalizeStatement: {0}", localHandle));
                }
                catch
                {
                }
#endif
#else
                lock (syncRoot)
................................................................................
#endif
            {
#if !NET_COMPACT_20 && TRACE_HANDLE
                try
                {
                    Trace.WriteLine(String.Format(
                        "FinalizeStatement: {0}, exception: {1}",
                        handle, e));
                }
                catch
                {
                }
#endif
            }
            finally
................................................................................
                if (localHandle != IntPtr.Zero)
                    SQLiteBase.FinishBackup(cnn, localHandle);

#if !NET_COMPACT_20 && TRACE_HANDLE
                try
                {
                    Trace.WriteLine(String.Format(
                        "FinishBackup: {0}", localHandle));
                }
                catch
                {
                }
#endif
#else
                lock (syncRoot)
................................................................................
#endif
            {
#if !NET_COMPACT_20 && TRACE_HANDLE
                try
                {
                    Trace.WriteLine(String.Format(
                        "FinishBackup: {0}, exception: {1}",
                        handle, e));
                }
                catch
                {
                }
#endif
            }
            finally







>
>







 







<






<




>
>
>
>
>







 







<




|

<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









<




<
|




>







<
|

<
>
|
<
<
|
<
<
<
<
|
|
<
<
<
<
<
<







<
<
>
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
>







 







<





|








<
|

>
>
>







 







>
>
>




<
|
|
>
|
|
|
|
>
>
>
>
>


>

<
<
>
>
>







 







>
|









|

>
>







 







|
>







 







>
>
>





<
|
|
>
|
<
>
>
>
>
>







 







|








|
|







 







|







 







|







 







|







 







|







 







|







 







|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
..
68
69
70
71
72
73
74

75
76
77
78
79
80

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
...
202
203
204
205
206
207
208

209
210
211
212
213
214

215
216
217
218
219
220
221
...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454

455
456
457
458

459
460
461
462
463
464
465
466
467
468
469
470
471

472
473

474
475


476




477
478






479
480
481
482
483
484
485


486
487
488

















489
490
491
492
493
494
495
496
497
...
534
535
536
537
538
539
540

541
542
543
544
545
546
547
548
549
550
551
552
553
554

555
556
557
558
559
560
561
562
563
564
565
566
...
582
583
584
585
586
587
588
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611


612
613
614
615
616
617
618
619
620
621
...
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
...
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
...
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797

798
799
800
801

802
803
804
805
806
807
808
809
810
811
812
813
...
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
....
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
....
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
....
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
....
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
....
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
....
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
#endif

  using System.Runtime.InteropServices;

#if !PLATFORM_COMPACTFRAMEWORK || COUNT_HANDLE
  using System.Threading;
#endif

  using System.Xml;

#if !PLATFORM_COMPACTFRAMEWORK && !DEBUG
  [SuppressUnmanagedCodeSecurity]
#endif
  internal static class UnsafeNativeMethods
  {
      #region Critical Handle Counts (Debug Build Only)
................................................................................
#if SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK

      //
      // NOTE: Only compile in the native library pre-load code if the feature
      //       has been enabled for this build.
      //
#if PRELOAD_NATIVE_LIBRARY

      /// <summary>
      /// The name of the environment variable containing the processor
      /// architecture of the current process.
      /// </summary>
      private static readonly string PROCESSOR_ARCHITECTURE =
          "PROCESSOR_ARCHITECTURE";


      /////////////////////////////////////////////////////////////////////////

      private static readonly string DllFileExtension = ".dll";

      /////////////////////////////////////////////////////////////////////////

      private static readonly string XmlConfigurationFileName =
          typeof(UnsafeNativeMethods).Namespace + ".config";

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// This is the P/Invoke method that wraps the native Win32 LoadLibrary
      /// function.  See the MSDN documentation for full details on what it
      /// does.
      /// </summary>
................................................................................
      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Attempts to initialize this class by pre-loading the native SQLite
      /// library for the processor architecture of the current process.
      /// </summary>
      internal static void Initialize()
      {

          //
          // NOTE: If the "No_PreLoadSQLite" environment variable is set (to
          //       anything), skip all our special code and simply return.
          //
          if (GetVariableValue("No_PreLoadSQLite") != null)
              return;


          lock (staticSyncRoot)
          {
              //
              // TODO: Make sure this list is updated if the supported
              //       processor architecture names and/or platform names
              //       changes.
................................................................................
              if (_SQLiteModule == IntPtr.Zero)
                  _SQLiteModule = PreLoadSQLiteDll(null, null);
          }
      }

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      /// <returns>
      /// 
      /// </returns>
      private static string GetXmlConfigurationFileName()
      {
          string directory;
          string fileName;

#if !PLATFORM_COMPACTFRAMEWORK
          directory = AppDomain.CurrentDomain.BaseDirectory;
          fileName = Path.Combine(directory, XmlConfigurationFileName);

          if (File.Exists(fileName))
              return fileName;
#endif

          directory = GetAssemblyDirectory();
          fileName = Path.Combine(directory, XmlConfigurationFileName);

          if (File.Exists(fileName))
              return fileName;

          return null;
      }

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Queries and returns the value of the specified "configuration"
      /// variable, using the XML configuration file and/or the environment
      /// variables for the current process and/or the current system, when
      /// available.
      /// </summary>
      /// <param name="name">
      /// The name of the configuration variable.
      /// </param>
      /// <returns>
      /// The value of the configuration variable -OR- null if it cannot be
      /// determined.  By default, references to existing environment will
      /// be expanded within the returned value unless either the "No_Expand"
      /// or "No_Expand_<paramref name="name" />" environment variables are
      /// set.
      /// </returns>
      internal static string GetVariableValue(
          string name
          )
      {
          string value = null;

          if (name == null)
              return value;

#if !PLATFORM_COMPACTFRAMEWORK
          bool expand = true;

          if (Environment.GetEnvironmentVariable("No_Expand") != null)
          {
              expand = false;
          }
          else if (Environment.GetEnvironmentVariable(String.Format(
                  "No_Expand_{0}", name)) != null)
          {
              expand = false;
          }

          value = Environment.GetEnvironmentVariable(name);

          if (expand && !String.IsNullOrEmpty(value))
              value = Environment.ExpandEnvironmentVariables(value);

          if (value != null)
              return value;
#endif

          try
          {
              string fileName = GetXmlConfigurationFileName();

              if (fileName == null)
                  return value;

              XmlDocument document = new XmlDocument();

              document.Load(fileName);

              XmlElement element = document.SelectSingleNode(String.Format(
                  "/configuration/appSettings/add[@key='{0}']")) as XmlElement;

              if (element != null)
              {
                  value = element.GetAttribute("value");

                  if (String.IsNullOrEmpty(value))
                      value = null;
#if !PLATFORM_COMPACTFRAMEWORK
                  else if (expand)
                      value = Environment.ExpandEnvironmentVariables(value);
#endif
              }
          }
#if !NET_COMPACT_20 && TRACE_PRELOAD
          catch (Exception e)
#else
          catch (Exception)
#endif
          {
#if !NET_COMPACT_20 && TRACE_PRELOAD
              try
              {
                  Trace.WriteLine(String.Format(
                      CultureInfo.CurrentCulture,
                      "Native library pre-loader failed to get variable " +
                      "\"{0}\" value: {1}", name, e)); /* throw */
              }
              catch
              {
                  // do nothing.
              }
#endif
          }

          return value;
      }

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Queries and returns the directory for the assembly currently being
      /// executed.
      /// </summary>
      /// <returns>
      /// The directory for the assembly currently being executed -OR- null if
      /// it cannot be determined.
      /// </returns>
      private static string GetAssemblyDirectory()
      {
          try
          {
              Assembly assembly = Assembly.GetExecutingAssembly();

              if (assembly == null)
                  return null;

              string fileName;

#if PLATFORM_COMPACTFRAMEWORK
              AssemblyName assemblyName = assembly.GetName();

              if (assemblyName == null)
                  return null;

              fileName = assemblyName.CodeBase;
#else
              fileName = assembly.Location;
#endif

              if (String.IsNullOrEmpty(fileName))
                  return null;

              string directory = Path.GetDirectoryName(fileName);

              if (String.IsNullOrEmpty(directory))
                  return null;

              return directory;
          }
#if !NET_COMPACT_20 && TRACE_PRELOAD
          catch (Exception e)
#else
          catch (Exception)
#endif
          {
#if !NET_COMPACT_20 && TRACE_PRELOAD
              try
              {
                  Trace.WriteLine(String.Format(
                      CultureInfo.CurrentCulture,
                      "Native library pre-loader failed to get directory " +
                      "for currently executing assembly: {0}", e)); /* throw */
              }
              catch
              {
                  // do nothing.
              }
#endif
          }

          return null;
      }

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Queries and returns the base directory of the current application
      /// domain.
      /// </summary>
      /// <returns>
      /// The base directory for the current application domain -OR- null if it
      /// cannot be determined.
      /// </returns>
      private static string GetBaseDirectory()
      {

          //
          // NOTE: If the "PreLoadSQLite_BaseDirectory" environment variable
          //       is set, use it verbatim for the base directory.
          //

          string directory = GetVariableValue("PreLoadSQLite_BaseDirectory");

          if (directory != null)
              return directory;

#if !PLATFORM_COMPACTFRAMEWORK
          //
          // NOTE: If the "PreLoadSQLite_UseAssemblyDirectory" environment
          //       variable is set (to anything), attempt to use the directory
          //       containing the currently executing assembly (i.e.
          //       System.Data.SQLite) intsead of the application domain base
          //       directory.
          //

          if (GetVariableValue("PreLoadSQLite_UseAssemblyDirectory") != null)
          {

              directory = GetAssemblyDirectory();



              if (directory != null)




                  return directory;
          }







          //
          // NOTE: Otherwise, fallback on using the base directory of the
          //       current application domain.
          //
          return AppDomain.CurrentDomain.BaseDirectory;
#else


          //
          // NOTE: Otherwise, fallback on using the directory containing
          //       the currently executing assembly.

















          //
          return GetAssemblyDirectory();
#endif
      }

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Determines if the dynamic link library file name requires a suffix
      /// and adds it if necessary.
................................................................................
      /// </summary>
      /// <returns>
      /// The processor architecture of the current process -OR- null if it
      /// cannot be determined.
      /// </returns>
      private static string GetProcessorArchitecture()
      {

          //
          // NOTE: If the "PreLoadSQLite_ProcessorArchitecture" environment
          //       variable is set, use it verbatim for the current processor
          //       architecture.
          //
          string processorArchitecture = GetVariableValue(
              "PreLoadSQLite_ProcessorArchitecture");

          if (processorArchitecture != null)
              return processorArchitecture;

          //
          // BUGBUG: Will this always be reliable?
          //

          processorArchitecture = GetVariableValue(PROCESSOR_ARCHITECTURE);

          /////////////////////////////////////////////////////////////////////

#if !PLATFORM_COMPACTFRAMEWORK
          //
          // HACK: Check for an "impossible" situation.  If the pointer size
          //       is 32-bits, the processor architecture cannot be "AMD64".
          //       In that case, we are almost certainly hitting a bug in the
          //       operating system and/or Visual Studio that causes the
          //       PROCESSOR_ARCHITECTURE environment variable to contain the
          //       wrong value in some circumstances.  Please refer to ticket
................................................................................
              // NOTE: We know that operating systems that return "AMD64" as
              //       the processor architecture are actually a superset of
              //       the "x86" processor architecture; therefore, return
              //       "x86" when the pointer size is 32-bits.
              //
              processorArchitecture = "x86";

#if !NET_COMPACT_20 && TRACE_PRELOAD
              try
              {
                  //
                  // NOTE: Show that we hit a fairly unusual situation (i.e. the
                  //       "wrong" processor architecture was detected).
                  //

                  Trace.WriteLine(String.Format(
                      CultureInfo.CurrentCulture,
                      "Native library pre-loader detected {0}-bit pointer " +
                      "size with processor architecture \"{1}\", using " +
                      "processor architecture \"{2}\" instead...",
                      IntPtr.Size * 8 /* bits */, savedProcessorArchitecture,
                      processorArchitecture)); /* throw */
              }
              catch
              {
                  // do nothing.
              }
#endif
          }
#endif



          /////////////////////////////////////////////////////////////////////

#if PLATFORM_COMPACTFRAMEWORK
          //
          // NOTE: On the .NET Compact Framework, attempt to use the native
          //       Win32 API function (via P/Invoke) that can provide us with
          //       the processor architecture.
          //
          try
          {
................................................................................
              //       the structure.
              //
              GetSystemInfo(out systemInfo);

              //
              // NOTE: Return the processor architecture value as a string.
              //
              processorArchitecture =
                  systemInfo.wProcessorArchitecture.ToString();
          }
          catch
          {
              // do nothing.
          }

          //
          // NOTE: Upon failure, return an empty string.
          //
          processorArchitecture = String.Empty;
#endif

          return processorArchitecture;
      }

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Given the processor architecture, returns the name of the platform.
      /// </summary>
      /// <param name="processorArchitecture">
................................................................................
      /// </returns>
      private static IntPtr PreLoadSQLiteDll(
          string directory,
          string processorArchitecture
          )
      {
          //
          // NOTE: If the specified base directory is null, use the default
          //       (i.e. attempt to automatically detect it).
          //
          if (directory == null)
              directory = GetBaseDirectory();

          //
          // NOTE: If we failed to query the base directory, stop now.
          //
................................................................................
              // NOTE: If the file does not exist, skip trying to load it.
              //
              if (!File.Exists(fileName))
                  return IntPtr.Zero;
          }

          try
          {
#if !NET_COMPACT_20 && TRACE_PRELOAD
              try
              {
                  //
                  // NOTE: Show exactly where we are trying to load the native
                  //       SQLite library from.
                  //

                  Trace.WriteLine(String.Format(
                      CultureInfo.CurrentCulture,
                      "Native library pre-loader is trying to load native " +
                      "SQLite library \"{0}\"...", fileName)); /* throw */

              }
              catch
              {
                  // do nothing.
              }
#endif

              //
              // NOTE: Attempt to load the native library.  This will either
              //       return a valid native module handle, return IntPtr.Zero,
              //       or throw an exception.
              //
................................................................................
          {
#if !NET_COMPACT_20 && TRACE_PRELOAD
              try
              {
                  //
                  // NOTE: First, grab the last Win32 error number.
                  //
                  int lastError = Marshal.GetLastWin32Error(); /* throw */

                  //
                  // NOTE: Show where we failed to load the native SQLite
                  //       library from along with the Win32 error code and
                  //       exception information.
                  //
                  Trace.WriteLine(String.Format(
                      CultureInfo.CurrentCulture,
                      "Native library pre-loader failed to load native " +
                      "SQLite library \"{0}\" (getLastError = {1}): {2}",
                      fileName, lastError, e)); /* throw */
              }
              catch
              {
                  // do nothing.
              }
#endif
................................................................................
                    SQLiteBase.CloseConnection(this, localHandle);
#endif

#if !NET_COMPACT_20 && TRACE_HANDLE
                try
                {
                    Trace.WriteLine(String.Format(
                        "CloseConnection: {0}", localHandle)); /* throw */
                }
                catch
                {
                }
#endif
#else
                lock (syncRoot)
................................................................................
#endif
            {
#if !NET_COMPACT_20 && TRACE_HANDLE
                try
                {
                    Trace.WriteLine(String.Format(
                        "CloseConnection: {0}, exception: {1}",
                        handle, e)); /* throw */
                }
                catch
                {
                }
#endif
            }
            finally
................................................................................
                if (localHandle != IntPtr.Zero)
                    SQLiteBase.FinalizeStatement(cnn, localHandle);

#if !NET_COMPACT_20 && TRACE_HANDLE
                try
                {
                    Trace.WriteLine(String.Format(
                        "FinalizeStatement: {0}", localHandle)); /* throw */
                }
                catch
                {
                }
#endif
#else
                lock (syncRoot)
................................................................................
#endif
            {
#if !NET_COMPACT_20 && TRACE_HANDLE
                try
                {
                    Trace.WriteLine(String.Format(
                        "FinalizeStatement: {0}, exception: {1}",
                        handle, e)); /* throw */
                }
                catch
                {
                }
#endif
            }
            finally
................................................................................
                if (localHandle != IntPtr.Zero)
                    SQLiteBase.FinishBackup(cnn, localHandle);

#if !NET_COMPACT_20 && TRACE_HANDLE
                try
                {
                    Trace.WriteLine(String.Format(
                        "FinishBackup: {0}", localHandle)); /* throw */
                }
                catch
                {
                }
#endif
#else
                lock (syncRoot)
................................................................................
#endif
            {
#if !NET_COMPACT_20 && TRACE_HANDLE
                try
                {
                    Trace.WriteLine(String.Format(
                        "FinishBackup: {0}, exception: {1}",
                        handle, e)); /* throw */
                }
                catch
                {
                }
#endif
            }
            finally