@@ -396,12 +396,8 @@ char* cleanup_passwd(char* arg)
396
396
397
397
#ifdef WIN_NT
398
398
399
- static bool validateProductSuite (LPCSTR lpszSuiteToValidate);
400
-
401
- // hvlad: begins from Windows 2000 we can safely add 'Global\' prefix for
402
- // names of all kernel objects we use. For Win9x we must not add this prefix.
403
- // Win NT will accept such names only if Terminal Server is installed.
404
- // Check OS version carefully and add prefix if we can add it
399
+ // With sufficient privileges, we can add 'Global\' prefix for
400
+ // names of all kernel objects we use.
405
401
406
402
bool prefix_kernel_object_name (char * name, size_t bufsize)
407
403
{
@@ -430,135 +426,51 @@ bool prefix_kernel_object_name(char* name, size_t bufsize)
430
426
431
427
memmove (name + move_prefix, name, len_name);
432
428
memcpy (name, prefix, move_prefix);
433
- // CVC: Unfortunately, things like Glob instead of Global\\ do not achieve the objective
434
- // of telling the NT kernel the object is global and hence I consider them failures.
435
- // return move_prefix > 0; // Soft version of the check
436
- return move_prefix == len_prefix; // Strict version of the check.
429
+ return move_prefix == len_prefix;
437
430
}
438
431
return true ;
439
432
}
440
433
441
-
442
- // Simply handle guardian.
443
- class DynLibHandle
444
- {
445
- public:
446
- explicit DynLibHandle (HMODULE mod)
447
- : m_handle(mod)
448
- {}
449
- ~DynLibHandle ()
450
- {
451
- if (m_handle)
452
- FreeLibrary (m_handle);
453
- }
454
- operator HMODULE () const
455
- {
456
- return m_handle;
457
- }
458
- /* The previous conversion is invoked with !object so this is enough.
459
- bool operator!() const
460
- {
461
- return !m_handle;
462
- }
463
- */
464
- private:
465
- HMODULE m_handle;
466
- };
467
-
468
-
469
- // hvlad: two functions below got from
470
- // http://msdn2.microsoft.com/en-us/library/aa380797.aspx
471
- // and slightly adapted for our coding style
472
-
473
- // -------------------------------------------------------------
474
- // Note that the validateProductSuite and isTerminalServices
475
- // functions use ANSI versions of the functions to maintain
476
- // compatibility with Windows Me/98/95.
477
- // -------------------------------------------------------------
478
-
479
434
bool isGlobalKernelPrefix ()
480
435
{
481
436
// The strategy of this function is as follows: use Global\ kernel namespace
482
- // for engine objects if we can. This can be prevented by either lack of OS support
483
- // for the feature (Win9X) or lack of privileges (Vista, Windows 2000/XP restricted accounts)
437
+ // for engine objects if we can.
484
438
485
- const DWORD dwVersion = GetVersion ();
439
+ // Check if we have enough privileges to create global handles.
440
+ // If not fall back to creating local ones.
486
441
487
- // Is Windows NT running?
488
- if (!(dwVersion & 0x80000000 ))
442
+ HANDLE hProcess = GetCurrentProcess ();
443
+ HANDLE hToken;
444
+ if (OpenProcessToken (hProcess, TOKEN_QUERY, &hToken) == 0 )
489
445
{
490
- if (LOBYTE (LOWORD (dwVersion)) <= 4 ) // This is Windows NT 4.0 or earlier.
491
- return validateProductSuite (" Terminal Server" );
492
-
493
- // Is it Windows 2000 or greater? It is possible to use Global\ prefix on any
494
- // version of Windows from Windows 2000 and up
495
- // Check if we have enough privileges to create global handles.
496
- // If not fall back to creating local ones.
497
- // The API for that is the NT thing, so we have to get addresses of the
498
- // functions dynamically to avoid troubles on Windows 9X platforms
499
-
500
- DynLibHandle hmodAdvApi (LoadLibrary (" advapi32.dll" ));
501
-
502
- if (!hmodAdvApi)
503
- {
504
- gds__log (" LoadLibrary failed for advapi32.dll. Error code: %lu" , GetLastError ());
505
- return false ;
506
- }
507
-
508
- typedef BOOL (WINAPI *PFnOpenProcessToken) (HANDLE, DWORD, PHANDLE);
509
- typedef BOOL (WINAPI *PFnLookupPrivilegeValue) (LPCSTR, LPCSTR, PLUID);
510
- typedef BOOL (WINAPI *PFnPrivilegeCheck) (HANDLE, PPRIVILEGE_SET, LPBOOL);
511
-
512
- PFnOpenProcessToken pfnOpenProcessToken =
513
- (PFnOpenProcessToken) GetProcAddress (hmodAdvApi, " OpenProcessToken" );
514
- PFnLookupPrivilegeValue pfnLookupPrivilegeValue =
515
- (PFnLookupPrivilegeValue) GetProcAddress (hmodAdvApi, " LookupPrivilegeValueA" );
516
- PFnPrivilegeCheck pfnPrivilegeCheck =
517
- (PFnPrivilegeCheck) GetProcAddress (hmodAdvApi, " PrivilegeCheck" );
518
-
519
- if (!pfnOpenProcessToken || !pfnLookupPrivilegeValue || !pfnPrivilegeCheck)
520
- {
521
- // Should never happen, really
522
- gds__log (" Cannot access privilege management API" );
523
- return false ;
524
- }
525
-
526
- HANDLE hProcess = GetCurrentProcess ();
527
- HANDLE hToken;
528
- if (pfnOpenProcessToken (hProcess, TOKEN_QUERY, &hToken) == 0 )
529
- {
530
- gds__log (" OpenProcessToken failed. Error code: %lu" , GetLastError ());
531
- return false ;
532
- }
533
-
534
- PRIVILEGE_SET ps;
535
- memset (&ps, 0 , sizeof (ps));
536
- ps.Control = PRIVILEGE_SET_ALL_NECESSARY;
537
- ps.PrivilegeCount = 1 ;
538
- if (pfnLookupPrivilegeValue (NULL , TEXT (" SeCreateGlobalPrivilege" ), &ps.Privilege [0 ].Luid ) == 0 )
539
- {
540
- // Failure here means we're running on old version of Windows 2000 or XP
541
- // which always allow creating global handles
542
- CloseHandle (hToken);
543
- return true ;
544
- }
545
-
546
- BOOL checkResult;
547
- if (pfnPrivilegeCheck (hToken, &ps, &checkResult) == 0 )
548
- {
549
- gds__log (" PrivilegeCheck failed. Error code: %lu" , GetLastError ());
550
- CloseHandle (hToken);
551
- return false ;
552
- }
446
+ gds__log (" OpenProcessToken failed. Error code: %lu" , GetLastError ());
447
+ return false ;
448
+ }
553
449
450
+ PRIVILEGE_SET ps{};
451
+ ps.Control = PRIVILEGE_SET_ALL_NECESSARY;
452
+ ps.PrivilegeCount = 1 ;
453
+ if (LookupPrivilegeValue (NULL , TEXT (" SeCreateGlobalPrivilege" ), &ps.Privilege [0 ].Luid ) == 0 )
454
+ {
455
+ // Failure here means we're running on old version of Windows 2000 or XP
456
+ // which always allow creating global handles;
457
+ // we don't run on those versions anymore, but leave this as is.
554
458
CloseHandle (hToken);
459
+ return true ;
460
+ }
555
461
556
- return checkResult;
462
+ BOOL checkResult;
463
+ if (PrivilegeCheck (hToken, &ps, &checkResult) == 0 )
464
+ {
465
+ gds__log (" PrivilegeCheck failed. Error code: %lu" , GetLastError ());
466
+ CloseHandle (hToken);
467
+ return false ;
557
468
}
558
469
559
- return false ;
560
- }
470
+ CloseHandle (hToken);
561
471
472
+ return checkResult;
473
+ }
562
474
563
475
// Incapsulates Windows private namespace
564
476
class PrivateNamespace
@@ -726,164 +638,6 @@ bool privateNameSpaceReady()
726
638
return privateNamespace ().isReady ();
727
639
}
728
640
729
-
730
- // This is a very basic registry querying class. Not much validation, but avoids
731
- // leaving the registry open by mistake.
732
-
733
- class NTRegQuery
734
- {
735
- public:
736
- NTRegQuery ();
737
- ~NTRegQuery ();
738
- bool openForRead (const char * key);
739
- bool readValueSize (const char * value);
740
- // Assumes previous call to readValueSize.
741
- bool readValueData (LPSTR data);
742
- void close ();
743
- DWORD getDataType () const ;
744
- DWORD getDataSize () const ;
745
- private:
746
- HKEY m_hKey;
747
- DWORD m_dwType;
748
- DWORD m_dwSize;
749
- const char * m_value;
750
- };
751
-
752
- inline NTRegQuery::NTRegQuery ()
753
- : m_hKey(NULL ), m_dwType(0 ), m_dwSize(0 )
754
- {
755
- }
756
-
757
- inline NTRegQuery::~NTRegQuery ()
758
- {
759
- close ();
760
- }
761
-
762
- bool NTRegQuery::openForRead (const char * key)
763
- {
764
- return RegOpenKeyExA (HKEY_LOCAL_MACHINE, key, 0 , KEY_QUERY_VALUE, &m_hKey) == ERROR_SUCCESS;
765
- }
766
-
767
- bool NTRegQuery::readValueSize (const char * value)
768
- {
769
- m_value = value;
770
- return RegQueryValueExA (m_hKey, value, NULL , &m_dwType, NULL , &m_dwSize) == ERROR_SUCCESS;
771
- }
772
-
773
- bool NTRegQuery::readValueData (LPSTR data)
774
- {
775
- return RegQueryValueExA (m_hKey, m_value, NULL , &m_dwType, (LPBYTE) data, &m_dwSize) == ERROR_SUCCESS;
776
- }
777
-
778
- void NTRegQuery::close ()
779
- {
780
- if (m_hKey)
781
- RegCloseKey (m_hKey);
782
-
783
- m_hKey = NULL ;
784
- }
785
-
786
- inline DWORD NTRegQuery::getDataType () const
787
- {
788
- return m_dwType;
789
- }
790
-
791
- inline DWORD NTRegQuery::getDataSize () const
792
- {
793
- return m_dwSize;
794
- }
795
-
796
-
797
- // This class represents the local allocation of dynamic memory in Windows.
798
-
799
- class NTLocalString
800
- {
801
- public:
802
- explicit NTLocalString (DWORD dwSize);
803
- LPCSTR c_str () const ;
804
- LPSTR getString ();
805
- bool allocated () const ;
806
- ~NTLocalString ();
807
- private:
808
- LPSTR m_string;
809
- };
810
-
811
- NTLocalString::NTLocalString (DWORD dwSize)
812
- {
813
- m_string = (LPSTR) LocalAlloc (LPTR, dwSize);
814
- }
815
-
816
- NTLocalString::~NTLocalString ()
817
- {
818
- if (m_string)
819
- LocalFree (m_string);
820
- }
821
-
822
- inline LPCSTR NTLocalString::c_str () const
823
- {
824
- return m_string;
825
- }
826
-
827
- inline LPSTR NTLocalString::getString ()
828
- {
829
- return m_string;
830
- }
831
-
832
- inline bool NTLocalString::allocated () const
833
- {
834
- return m_string != 0 ;
835
- }
836
-
837
-
838
- // //////////////////////////////////////////////////////////
839
- // validateProductSuite function
840
- //
841
- // Terminal Services detection code for systems running
842
- // Windows NT 4.0 and earlier.
843
- //
844
- // //////////////////////////////////////////////////////////
845
-
846
- bool validateProductSuite (LPCSTR lpszSuiteToValidate)
847
- {
848
- NTRegQuery query;
849
-
850
- // Open the ProductOptions key.
851
- if (!query.openForRead (" System\\ CurrentControlSet\\ Control\\ ProductOptions" ))
852
- return false ;
853
-
854
- // Determine required size of ProductSuite buffer.
855
- // If we get size == 1 it means multi string data with only a terminator.
856
- if (!query.readValueSize (" ProductSuite" ) || query.getDataSize () < 2 )
857
- return false ;
858
-
859
- // Allocate buffer.
860
- NTLocalString lpszProductSuites (query.getDataSize ());
861
- if (!lpszProductSuites.allocated ())
862
- return false ;
863
-
864
- // Retrieve array of product suite strings.
865
- if (!query.readValueData (lpszProductSuites.getString ()) || query.getDataType () != REG_MULTI_SZ)
866
- return false ;
867
-
868
- query.close (); // explicit but redundant.
869
-
870
- // Search for suite name in array of strings.
871
- bool fValidated = false ;
872
- LPCSTR lpszSuite = lpszProductSuites.c_str ();
873
- LPCSTR end = lpszSuite + query.getDataSize (); // paranoid check
874
- while (*lpszSuite && lpszSuite < end)
875
- {
876
- if (lstrcmpA (lpszSuite, lpszSuiteToValidate) == 0 )
877
- {
878
- fValidated = true ;
879
- break ;
880
- }
881
- lpszSuite += (lstrlenA (lpszSuite) + 1 );
882
- }
883
-
884
- return fValidated ;
885
- }
886
-
887
641
#endif // WIN_NT
888
642
889
643
// *******************************
0 commit comments