@@ -396,12 +396,8 @@ char* cleanup_passwd(char* arg)
396396
397397#ifdef WIN_NT
398398
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.
405401
406402bool prefix_kernel_object_name (char * name, size_t bufsize)
407403{
@@ -430,135 +426,51 @@ bool prefix_kernel_object_name(char* name, size_t bufsize)
430426
431427 memmove (name + move_prefix, name, len_name);
432428 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;
437430 }
438431 return true ;
439432}
440433
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-
479434bool isGlobalKernelPrefix ()
480435{
481436 // 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.
484438
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.
486441
487- // Is Windows NT running?
488- if (!(dwVersion & 0x80000000 ))
442+ HANDLE hProcess = GetCurrentProcess ();
443+ HANDLE hToken;
444+ if (OpenProcessToken (hProcess, TOKEN_QUERY, &hToken) == 0 )
489445 {
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+ }
553449
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.
554458 CloseHandle (hToken);
459+ return true ;
460+ }
555461
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 ;
557468 }
558469
559- return false ;
560- }
470+ CloseHandle (hToken);
561471
472+ return checkResult;
473+ }
562474
563475// Incapsulates Windows private namespace
564476class PrivateNamespace
@@ -726,164 +638,6 @@ bool privateNameSpaceReady()
726638 return privateNamespace ().isReady ();
727639}
728640
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-
887641#endif // WIN_NT
888642
889643// *******************************
0 commit comments