/* dbg.cpp */ #include "precomp.h" #include #include #include #include #include #include PSECURITY_DESCRIPTOR CreateSd( VOID); BOOL CreateSids( PSID *BuiltInAdministrators, PSID *PowerUsers, PSID *AuthenticatedUsers); #ifdef NM_DEBUG /* Almost the whole file */ // Special Debugbreak macro #if defined (_M_IX86) #define _DbgBreak() __asm { int 3 } #else #define _DbgBreak() DebugBreak() #endif // Special Mutex Macros #define ACQMUTEX(hMutex) WaitForSingleObject(hMutex, INFINITE) #define RELMUTEX(hMutex) ReleaseMutex(hMutex) // Constant for GlobalAddAtom const int CCHMAX_ATOM = 255; // Local Variables static PNMDBG _gpDbg = NULL; // Shared data in mmf after zone info static HANDLE _ghMutexFile = NULL; // Mutex for writing to file static PZONEINFO _gprgZoneInfo = NULL; // the address in which the zone is mapped,points to an array of zones static HANDLE _ghDbgZoneMap = NULL; // the handle of the memory mapped file for zones static HANDLE _ghDbgZoneMutex = NULL; // Mutex for accessing Zone information static long _gLockCount = 0; VOID DbgCurrentTime(PCHAR psz); /* _ D B G P R I N T F */ /*------------------------------------------------------------------------- %%Function: _DbgPrintf The main, low level, debug output routine. -------------------------------------------------------------------------*/ static VOID WINAPI _DbgPrintf(LPCSTR pszFile, PCSTR pszPrefix, PCSTR pszFormat, va_list ap) { CHAR szOutput[1024]; PCHAR pszOutput = szOutput; UINT cch; if (NULL == _gprgZoneInfo) return; if (DBG_FMTTIME_NONE != _gpDbg->uShowTime) { DbgCurrentTime(pszOutput); pszOutput += lstrlenA(pszOutput); } if (_gpDbg->fShowThreadId) { wsprintfA(pszOutput, "[%04X] ", GetCurrentThreadId()); pszOutput += lstrlenA(pszOutput); } if (_gpDbg->fShowModule) { CHAR szFile[MAX_PATH]; if ((NULL == pszPrefix) || ('\0' == *pszPrefix)) { GetModuleFileNameA(NULL, szFile, sizeof(szFile)); pszPrefix = ExtractFileNameA(szFile); } lstrcpyA(pszOutput, pszPrefix); pszOutput += lstrlenA(pszOutput); lstrcpyA(pszOutput, " "); pszOutput += 1; } wvsprintfA(pszOutput, pszFormat, ap); // Append carriage return, if necessary // WARNING: This code is not DBCS-safe. cch = lstrlenA(szOutput); if (szOutput[cch-1] == '\n') { if (szOutput[cch-2] != '\r') { lstrcpyA(&szOutput[cch-1], "\r\n"); cch++; } } else { lstrcpyA(&szOutput[cch], "\r\n"); cch += 2; } // Output to debug handler if (_gpDbg->fOutputDebugString) { OutputDebugStringA(szOutput); } // Output to File if (_gpDbg->fFileOutput || (NULL != pszFile)) { HANDLE hFile; DWORD dw; // Lock access to file ACQMUTEX(_ghMutexFile); if (NULL == pszFile) pszFile = _gpDbg->szFile; // open a log file for appending. create if does not exist hFile = CreateFileA(pszFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL); if (hFile != INVALID_HANDLE_VALUE) { // seek to end of file dw = SetFilePointer(hFile, 0, NULL, FILE_END); #ifdef TEST /* Test/Retail version truncates at 40K */ if (dw > 0x040000) { CloseHandle(hFile); hFile = CreateFileA(pszFile, GENERIC_WRITE, 0, NULL, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL); } if (INVALID_HANDLE_VALUE != hFile) #endif { WriteFile(hFile, szOutput, lstrlenA(szOutput), &dw, NULL); CloseHandle(hFile); } } // Unlock access to file RELMUTEX(_ghMutexFile); } // Output to viewer. This is at the end of the function because // we potentially truncate szOutput. if ((_gpDbg->fWinOutput) && (NULL != _gpDbg->hwndCtrl)) { // Make sure that the string doesn't exceed the maximum atom size. // WARNING: This code is not DBCS-safe. static const CHAR szTruncatedSuffix[] = "...\r\n"; static const int cchTruncatedSuffix = ARRAY_ELEMENTS(szTruncatedSuffix) - 1; if (CCHMAX_ATOM < cch) { lstrcpyA(&szOutput[CCHMAX_ATOM - cchTruncatedSuffix], szTruncatedSuffix); } ATOM aDbgAtom = GlobalAddAtomA(szOutput); if (aDbgAtom) { if (!PostMessage(_gpDbg->hwndCtrl, _gpDbg->msgDisplay, (WPARAM)aDbgAtom, 0L)) { // Unable to post Message, so free the atom GlobalDeleteAtom(aDbgAtom); } } } } PSTR WINAPI DbgZPrintf(HDBGZONE hZone, UINT iZone, PSTR pszFormat,...) { CHAR sz[MAXSIZE_OF_MODULENAME+MAXSIZE_OF_ZONENAME+1]; PCHAR psz; va_list v1; va_start(v1, pszFormat); if ((NULL != hZone) && (iZone < MAXNUM_OF_ZONES)) { wsprintfA(sz, "%hs:%hs", ((PZONEINFO) hZone)->pszModule, ((PZONEINFO) hZone)->szZoneNames[iZone]); psz = sz; } else { psz = NULL; } if ((NULL != hZone) && ('\0' != ((PZONEINFO) hZone)->szFile[0])) { // Use the private module output filename, if specified _DbgPrintf(((PZONEINFO) hZone)->szFile, psz, pszFormat, v1); } else { _DbgPrintf(NULL, psz, pszFormat, v1); } va_end(v1); return pszFormat; } PSTR WINAPI DbgZVPrintf(HDBGZONE hZone, UINT iZone, PSTR pszFormat, va_list ap) { CHAR sz[MAXSIZE_OF_MODULENAME+MAXSIZE_OF_ZONENAME+1]; PCHAR psz; if ((NULL != hZone) && (iZone < MAXNUM_OF_ZONES)) { wsprintfA(sz, "%hs:%hs", ((PZONEINFO) hZone)->pszModule, ((PZONEINFO) hZone)->szZoneNames[iZone]); psz = sz; } else { psz = NULL; } if ((NULL != hZone) && ('\0' != ((PZONEINFO) hZone)->szFile[0])) { // Use the private module output filename, if specified _DbgPrintf(((PZONEINFO) hZone)->szFile, psz, pszFormat, ap); } else { _DbgPrintf(NULL, psz, pszFormat, ap); } return pszFormat; } VOID WINAPI DbgPrintf(PCSTR pszPrefix, PCSTR pszFormat, va_list ap) { _DbgPrintf(NULL, pszPrefix, pszFormat, ap); } VOID NMINTERNAL DbgInitEx(HDBGZONE * phDbgZone, PCHAR * psz, UINT cZones, long ulZoneDefault) { UINT i; HDBGZONE hDbgZone; DBGZONEINFO dbgZoneParm; //DbgMsg("Module %s (%d zones)", *psz, cZones); InterlockedIncrement( &_gLockCount ); InitDbgZone(); if (cZones > MAXNUM_OF_ZONES) cZones = MAXNUM_OF_ZONES; ZeroMemory(&dbgZoneParm, sizeof(dbgZoneParm)); // First string is the module name lstrcpynA(dbgZoneParm.pszModule, *psz, CCHMAX(dbgZoneParm.pszModule)); // Copy the zone names for (i = 0; i < cZones; i++) { lstrcpynA(dbgZoneParm.szZoneNames[i], psz[1+i], CCHMAX(dbgZoneParm.szZoneNames[0])); } // Get the detault zone settings { RegEntry reZones(ZONES_KEY, HKEY_LOCAL_MACHINE); dbgZoneParm.ulZoneMask = reZones.GetNumber(CUSTRING(dbgZoneParm.pszModule), ulZoneDefault); } hDbgZone = NmDbgCreateZone(dbgZoneParm.pszModule); if (NULL == hDbgZone) { OutputDebugStringA("DbgInit: Failed to create zones!\r\n"); return; } NmDbgSetZone(hDbgZone, &dbgZoneParm); *phDbgZone = hDbgZone; } VOID NMINTERNAL DbgDeInit(HDBGZONE * phDbgZone) { if (NULL == phDbgZone) return; if (NULL == *phDbgZone) return; //DbgMsg("Freeing Zone [%s]",((PZONEINFO)(*phDbgZone))->pszModule); NmDbgDeleteZone("", *phDbgZone); *phDbgZone = NULL; if( 0 == InterlockedDecrement( &_gLockCount ) ) { UnMapDebugZoneArea(); if( _ghMutexFile ) { CloseHandle( _ghMutexFile ); _ghMutexFile = NULL; } if( _ghDbgZoneMutex ) { CloseHandle( _ghDbgZoneMutex ); _ghDbgZoneMutex = NULL; } } } ////////////////////////////////////////////////////////////////////////////////// // from dbgzone.cpp /*************************************************************************** Name : NmDbgCreateZones Purpose : A module calls this to allocate/initialize the zone area for debugging purposes. Parameters: pszName - the name of the module Returns : Comment : ***************************************************************************/ HDBGZONE WINAPI NmDbgCreateZone(LPSTR pszName) { PZONEINFO pZoneInfo=NULL; if (!(pZoneInfo = FindZoneForModule(pszName))) pZoneInfo = AllocZoneForModule(pszName); return ((HDBGZONE)pZoneInfo); } /*************************************************************************** Name : NmDbgDeleteZones Purpose : Parameters: Returns : Comment : ***************************************************************************/ void WINAPI NmDbgDeleteZone(LPSTR pszName, HDBGZONE hDbgZone) { //decrement reference count PZONEINFO pZoneInfo = (PZONEINFO)hDbgZone; ASSERT( _ghDbgZoneMutex ); ACQMUTEX(_ghDbgZoneMutex); if (pZoneInfo) { pZoneInfo->ulRefCnt--; if (pZoneInfo->ulRefCnt == 0) { pZoneInfo->bInUse = FALSE; pZoneInfo->ulSignature = 0; } } RELMUTEX(_ghDbgZoneMutex); } /*************************************************************************** Name : NmDbgSetZones Purpose : Parameters: Returns : Comment : ***************************************************************************/ BOOL WINAPI NmDbgSetZone(HDBGZONE hDbgZone, PDBGZONEINFO pZoneParam) { PZONEINFO pZoneInfo = (PZONEINFO)hDbgZone; if (!pZoneInfo) return FALSE; if (lstrcmpA(pZoneInfo->pszModule,pZoneParam->pszModule)) return FALSE; pZoneInfo->ulZoneMask = pZoneParam->ulZoneMask; CopyMemory(pZoneInfo->szZoneNames, pZoneParam->szZoneNames, (sizeof(CHAR) * MAXNUM_OF_ZONES * MAXSIZE_OF_ZONENAME)); return(TRUE); } /*************************************************************************** Name : NmDbgGetZoneParams Purpose : Parameters: Returns : Comment : ***************************************************************************/ BOOL WINAPI NmDbgGetAllZoneParams(PDBGZONEINFO *plpZoneParam,LPUINT puCnt) { UINT ui; PZONEINFO pCurZone; if ((NULL == plpZoneParam) || (NULL == puCnt)) return FALSE; ACQMUTEX(_ghDbgZoneMutex); *puCnt = 0; for (pCurZone = _gprgZoneInfo, ui=0; uibInUse) && (pCurZone->ulSignature == ZONEINFO_SIGN)) { (*puCnt)++; } } *plpZoneParam = _gprgZoneInfo; RELMUTEX(_ghDbgZoneMutex); return TRUE; } BOOL WINAPI NmDbgFreeZoneParams(PDBGZONEINFO pZoneParam) { return TRUE; } PZONEINFO NMINTERNAL FindZoneForModule(LPCSTR pszModule) { int i; PZONEINFO pCurZone; for (pCurZone = _gprgZoneInfo,i=0;ibInUse) && (pCurZone->ulSignature == ZONEINFO_SIGN) && (!lstrcmpA(pCurZone->pszModule,pszModule))) { ACQMUTEX(_ghDbgZoneMutex); pCurZone->ulRefCnt++; RELMUTEX(_ghDbgZoneMutex); return pCurZone; } } return NULL; } /*************************************************************************** Name : AllocZoneForModule Purpose : Allocates the Parameters: Returns : Comment : ***************************************************************************/ PZONEINFO NMINTERNAL AllocZoneForModule(LPCSTR pszModule) { int i; PZONEINFO pCurZone; PZONEINFO pZoneForMod=NULL; ACQMUTEX(_ghDbgZoneMutex); for (pCurZone = _gprgZoneInfo,i=0; (ibInUse)) { pCurZone->bInUse = TRUE; pCurZone->ulSignature = ZONEINFO_SIGN; pCurZone->ulRefCnt = 1; lstrcpyA(pCurZone->pszModule, pszModule); pZoneForMod = pCurZone; break; } } RELMUTEX(_ghDbgZoneMutex); return(pZoneForMod); } VOID NMINTERNAL SetDbgFlags(void) { PTSTR psz; RegEntry reDebug(DEBUG_KEY, HKEY_LOCAL_MACHINE); _gpDbg->fOutputDebugString = reDebug.GetNumber(REGVAL_DBG_OUTPUT, DEFAULT_DBG_OUTPUT); _gpDbg->fWinOutput = reDebug.GetNumber(REGVAL_DBG_WIN_OUTPUT, DEFAULT_DBG_NO_WIN); _gpDbg->fFileOutput = reDebug.GetNumber(REGVAL_DBG_FILE_OUTPUT, DEFAULT_DBG_NO_FILE); _gpDbg->uShowTime = reDebug.GetNumber(REGVAL_DBG_SHOW_TIME, DBG_FMTTIME_NONE); _gpDbg->fShowThreadId = reDebug.GetNumber(REGVAL_DBG_SHOW_THREADID, 0); _gpDbg->fShowModule = reDebug.GetNumber(REGVAL_DBG_SHOW_MODULE, 0); psz = reDebug.GetString(REGVAL_DBG_FILE); if (0 != lstrlen(psz)) { lstrcpyA(_gpDbg->szFile, CUSTRING(psz)); } else { UINT cchFile; cchFile = GetWindowsDirectoryA(_gpDbg->szFile, CCHMAX(_gpDbg->szFile)); _gpDbg->szFile[cchFile++] = '\\'; lstrcpyA(_gpDbg->szFile + cchFile, CUSTRING(DEFAULT_DBG_FILENAME)); } } VOID InitZoneMmf(PZONEINFO prgZoneInfo) { ZeroMemory(prgZoneInfo, CBMMFDBG); SetDbgFlags(); } PZONEINFO NMINTERNAL MapDebugZoneArea(void) { PZONEINFO prgZoneInfo = NULL; BOOL fCreated; PSECURITY_DESCRIPTOR sd = NULL; SECURITY_ATTRIBUTES sa; // Obtain a true NULL security descriptor (so if running as a service, user processes can access it) // InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); // SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); // NULL DACL = wide open sd = CreateSd(); FillMemory(&sa, sizeof(sa), 0); sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = sd; //create a memory mapped object that is backed by paging file _ghDbgZoneMap = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, CBMMFDBG, SZ_DBG_MAPPED_ZONE); if (_ghDbgZoneMap) { fCreated = (0 == GetLastError()); prgZoneInfo = (PZONEINFO) MapViewOfFile(_ghDbgZoneMap, FILE_MAP_READ|FILE_MAP_WRITE, 0,0,0); if (NULL != prgZoneInfo) { // Grab pointer to shared data area _gpDbg = (PNMDBG) (((PBYTE) prgZoneInfo) + (MAXNUM_OF_MODULES * sizeof(ZONEINFO))); if (fCreated) InitZoneMmf(prgZoneInfo); } } if(sd) { HeapFree(GetProcessHeap(), 0, sd); } return prgZoneInfo; } VOID NMINTERNAL UnMapDebugZoneArea(void) { if (_gprgZoneInfo) { UnmapViewOfFile(_gprgZoneInfo); _gprgZoneInfo = NULL; } ClosePh(&_ghDbgZoneMap); } VOID NMINTERNAL InitDbgZone(void) { if (NULL != _gprgZoneInfo) return; // already initialized _gprgZoneInfo = MapDebugZoneArea(); // Create log file data PSECURITY_DESCRIPTOR sd = NULL; SECURITY_ATTRIBUTES sa; // Obtain a true NULL security descriptor (so if running as a service, user processes can access it) // InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); // SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); // NULL DACL = wide open sd = CreateSd(); FillMemory(&sa, sizeof(sa), 0); sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = sd; _ghMutexFile = CreateMutex(&sa, FALSE, SZ_DBG_FILE_MUTEX); _ghDbgZoneMutex = CreateMutex(&sa, FALSE, SZ_DBG_ZONE_MUTEX); if (_gpDbg->fFileOutput) { HANDLE hFile; DWORD dw; CHAR sz[MAX_PATH]; SYSTEMTIME systime; hFile = CreateFileA(_gpDbg->szFile, GENERIC_WRITE | GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hFile) { _gpDbg->fFileOutput = FALSE; goto cleanup; } GetLocalTime(&systime); wsprintfA(sz, "\r\n======== TRACE Started: %hu/%hu/%hu (%hu:%hu)\r\n", systime.wMonth, systime.wDay, systime.wYear, systime.wHour, systime.wMinute); SetFilePointer(hFile, 0, NULL, FILE_END); WriteFile(hFile, sz, lstrlenA(sz), &dw, NULL); CloseHandle(hFile); } cleanup: if (sd) { HeapFree(GetProcessHeap(), 0, sd); } } /////////////////////////////////////// // Routines for controlling debug output BOOL WINAPI NmDbgRegisterCtl(HWND hwnd, UINT uDisplayMsg) { if ((NULL == _gpDbg) || (NULL != _gpDbg->hwndCtrl)) return FALSE; _gpDbg->msgDisplay = uDisplayMsg; _gpDbg->hwndCtrl = hwnd; return TRUE; } BOOL WINAPI NmDbgDeregisterCtl(HWND hwnd) { if ((NULL == _gpDbg) || (hwnd != _gpDbg->hwndCtrl)) return FALSE; _gpDbg->hwndCtrl = NULL; _gpDbg->msgDisplay = 0; return TRUE; } BOOL WINAPI NmDbgSetLoggingOptions(HWND hwnd, UINT uOptions) { return FALSE; } PNMDBG WINAPI GetPNmDbg(void) { return _gpDbg; } VOID WINAPI NmDbgSetZoneFileName(HDBGZONE hZone, LPCSTR pszFile) { PSTR pszZoneFile; if (IsBadWritePtr((PVOID) hZone, sizeof(ZONEINFO))) return; if (((PZONEINFO) hZone)->ulSignature != ZONEINFO_SIGN) return; pszZoneFile = &(((PZONEINFO) hZone)->szFile[0]); if (NULL == pszFile) { *pszZoneFile = '\0'; } else { lstrcpynA(pszZoneFile, pszFile, CCHMAX(((PZONEINFO) hZone)->szFile)); } } /* D B G C U R R E N T T I M E */ /*------------------------------------------------------------------------- %%Function: DbgCurrentTime Format the current time -------------------------------------------------------------------------*/ VOID DbgCurrentTime(PCHAR psz) { if (DBG_FMTTIME_TICK == _gpDbg->uShowTime) { wsprintfA(psz, "[%04X] ", GetTickCount()); } else { SYSTEMTIME sysTime; GetLocalTime(&sysTime); switch (_gpDbg->uShowTime) { default: case DBG_FMTTIME_FULL: wsprintfA(psz, "[%04d/%02d/%02d %02d:%02d:%02d.%03d] ", sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds); break; case DBG_FMTTIME_DAY: wsprintfA(psz, "[%02d:%02d:%02d.%03d] ", sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds); break; } } } /* P S Z P R I N T F */ /*------------------------------------------------------------------------- %%Function: PszPrintf Utility function to wsprintf a string for debug. -------------------------------------------------------------------------*/ PSTR PszPrintf(PCSTR pszFormat,...) { PSTR psz = (PSTR) LocalAlloc(LMEM_FIXED, MAX_PATH); if (NULL != psz) { va_list v1; va_start(v1, pszFormat); wvsprintfA(psz, pszFormat, v1); va_end(v1); } return psz; } /* D E B U G T R A P F N */ /*------------------------------------------------------------------------- %%Function: DebugTrapFn -------------------------------------------------------------------------*/ VOID NMINTERNAL DebugTrapFn(VOID) { _DbgBreak(); } VOID DebugPrintfTraceMem(LPCSTR pszFormat,...) { // DO NOTHING va_list arglist; va_start(arglist, pszFormat); va_end(arglist); } #endif /* NM_DEBUG - almost the whole file */ /*************************************************************************/ const int RPF_UNKNOWN = 0; const int RPF_ENABLED = 1; const int RPF_DISABLED = 2; static int gRpf = RPF_UNKNOWN; static TCHAR gszRetailOutputFilename[MAX_PATH]; // retail trace filename /* F E N A B L E D R E T A I L P R I N T F */ /*------------------------------------------------------------------------- %%Function: FEnabledRetailPrintf Return TRUE if retail output is enabled. -------------------------------------------------------------------------*/ BOOL FEnabledRetailPrintf(VOID) { if (RPF_UNKNOWN == gRpf) { RegEntry reDebug(DEBUG_KEY, HKEY_LOCAL_MACHINE); gRpf = reDebug.GetNumber(REGVAL_RETAIL_LOG, RPF_DISABLED); if ((RPF_ENABLED != gRpf) || (!GetInstallDirectory(gszRetailOutputFilename)) ) { gRpf = RPF_DISABLED; } else { lstrcat(gszRetailOutputFilename, RETAIL_LOG_FILENAME); } } return (RPF_ENABLED == gRpf); } /* R E T A I L P R I N T F T R A C E */ /*------------------------------------------------------------------------- %%Function: RetailPrintfTrace Print retail information to a file -------------------------------------------------------------------------*/ VOID WINAPI RetailPrintfTrace(LPCSTR pszFormat,...) { HANDLE hFile; va_list v1; CHAR szOutput[1024]; if (!FEnabledRetailPrintf()) return; // Retail output is disabled va_start(v1, pszFormat); #ifdef DEBUG // Also use normal output mechanism for debug builds _DbgPrintf(NULL, "Retail:PrintfTrace", pszFormat, v1); #endif wvsprintfA(szOutput, pszFormat, v1); // Always append the CRLF ASSERT(lstrlenA(szOutput) < (CCHMAX(szOutput)-2)); lstrcatA(szOutput, "\r\n"); // open a log file for appending. create if does not exist hFile = CreateFile(gszRetailOutputFilename, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL); if (hFile != INVALID_HANDLE_VALUE) { // seek to end of file DWORD dw = SetFilePointer(hFile, 0, NULL, FILE_END); WriteFile(hFile, szOutput, lstrlenA(szOutput), &dw, NULL); CloseHandle(hFile); } va_end(v1); } // // CreateSids // // Create 3 Security IDs // // Caller must free memory allocated to SIDs on success. // // Returns: TRUE if successfull, FALSE if not. // BOOL CreateSids( PSID *BuiltInAdministrators, PSID *PowerUsers, PSID *AuthenticatedUsers ) { // // An SID is built from an Identifier Authority and a set of Relative IDs // (RIDs). The Authority of interest to us SECURITY_NT_AUTHORITY. // SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; // // Each RID represents a sub-unit of the authority. Two of the SIDs we // want to build, Local Administrators, and Power Users, are in the "built // in" domain. The other SID, for Authenticated users, is based directly // off of the authority. // // For examples of other useful SIDs consult the list in // \nt\public\sdk\inc\ntseapi.h. // if (!AllocateAndInitializeSid(&NtAuthority, 2, // 2 sub-authorities SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0,0,0,0,0,0, BuiltInAdministrators)) { // error } else if (!AllocateAndInitializeSid(&NtAuthority, 2, // 2 sub-authorities SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0,0,0,0,0,0, PowerUsers)) { // error FreeSid(*BuiltInAdministrators); *BuiltInAdministrators = NULL; } else if (!AllocateAndInitializeSid(&NtAuthority, 1, // 1 sub-authority SECURITY_AUTHENTICATED_USER_RID, 0,0,0,0,0,0,0, AuthenticatedUsers)) { // error FreeSid(*BuiltInAdministrators); *BuiltInAdministrators = NULL; FreeSid(*PowerUsers); *PowerUsers = NULL; } else { return TRUE; } return FALSE; } // // CreateSd // // Creates a SECURITY_DESCRIPTOR with specific DACLs. Modify the code to // change. // // Caller must free the returned buffer if not NULL. // PSECURITY_DESCRIPTOR CreateSd( VOID ) { PSID AuthenticatedUsers; PSID BuiltInAdministrators; PSID PowerUsers; if (!CreateSids(&BuiltInAdministrators, &PowerUsers, &AuthenticatedUsers)) { // error } else { // // Calculate the size of and allocate a buffer for the DACL, we need // this value independently of the total alloc size for ACL init. // PSECURITY_DESCRIPTOR Sd = NULL; ULONG AclSize; // // "- sizeof (ULONG)" represents the SidStart field of the // ACCESS_ALLOWED_ACE. Since we're adding the entire length of the // SID, this field is counted twice. // AclSize = sizeof (ACL) + (3 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (ULONG))) + GetLengthSid(AuthenticatedUsers) + GetLengthSid(BuiltInAdministrators) + GetLengthSid(PowerUsers); Sd = (PSECURITY_DESCRIPTOR) HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH + AclSize); if (!Sd) { // error } else { ACL *Acl; Acl = (ACL *)((BYTE *)Sd + SECURITY_DESCRIPTOR_MIN_LENGTH); if (!InitializeAcl(Acl, AclSize, ACL_REVISION)) { // error } else if (!AddAccessAllowedAce(Acl, ACL_REVISION, SYNCHRONIZE | GENERIC_READ, AuthenticatedUsers)) { // Failed to build the ACE granting "Authenticated users" // (SYNCHRONIZE | GENERIC_READ) access. } else if (!AddAccessAllowedAce(Acl, ACL_REVISION, SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE, PowerUsers)) { // Failed to build the ACE granting "Power users" // (SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE) access. } else if (!AddAccessAllowedAce(Acl, ACL_REVISION, GENERIC_ALL, BuiltInAdministrators)) { // Failed to build the ACE granting "Built-in Administrators" // GENERIC_ALL access. } else if (!InitializeSecurityDescriptor(Sd, SECURITY_DESCRIPTOR_REVISION)) { // error } else if (!SetSecurityDescriptorDacl(Sd, TRUE, Acl, FALSE)) { // error } else { FreeSid(AuthenticatedUsers); FreeSid(BuiltInAdministrators); FreeSid(PowerUsers); return Sd; } HeapFree(GetProcessHeap(), 0, Sd); } FreeSid(AuthenticatedUsers); FreeSid(BuiltInAdministrators); FreeSid(PowerUsers); } return NULL; }