Source code of Windows XP (NT5)
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.

703 lines
16 KiB

  1. /*
  2. * title: drvclass.cpp
  3. *
  4. * purpose: Implement C++ utilities
  5. *
  6. *
  7. */
  8. extern "C"
  9. {
  10. #include <ntddk.h>
  11. }
  12. #define BOOL BOOLEAN
  13. #define BYTE unsigned char
  14. #define PBYTE unsigned char *
  15. #include "drvclass.h"
  16. #define HidBattTag 'HtaB'
  17. extern "C" NTSTATUS DriverEntry (DRIVER_OBJECT *, UNICODE_STRING *);
  18. void * __cdecl operator new(size_t nSize, POOL_TYPE iType, ULONG iPoolTag)
  19. {
  20. return ExAllocatePoolWithTag(iType,nSize,iPoolTag);
  21. };
  22. void __cdecl operator delete(void* p)
  23. {
  24. ExFreePool(p);
  25. };
  26. // CUString::CUString()
  27. //
  28. // Default constructor. Creates an empty string.
  29. //
  30. CUString :: CUString()
  31. {
  32. m_String.MaximumLength = 0;
  33. m_String.Length = 0;
  34. m_String.Buffer = NULL;
  35. m_bType = TYPE_SYSTEM_ALLOCATED;
  36. m_status = STATUS_SUCCESS;
  37. }
  38. //
  39. // CUString::CUString( CUString& )
  40. //
  41. // Copy constructor
  42. //
  43. CUString :: CUString( CUString * pNewString )
  44. {
  45. /*
  46. RtlInitUnicodeString( &m_String, NULL );
  47. m_String.MaximumLength = NewString.m_String.MaximumLength;
  48. m_String.Length = 0;
  49. m_String.Buffer = ( unsigned short* )ExAllocatePoolWithTag( PagedPool, m_String.MaximumLength, HidBattTag );
  50. if( !m_String.Buffer )
  51. {
  52. m_status = STATUS_INSUFFICIENT_RESOURCES;
  53. return;
  54. }
  55. RtlZeroMemory( m_String.Buffer, m_String.MaximumLength );
  56. RtlAppendUnicodeStringToString( &m_String, &NewString.m_String );
  57. m_bType = TYPE_CLASS_ALLOCATED;
  58. m_status = STATUS_SUCCESS;
  59. m_String.Buffer[ m_String.Length ] = NULL;
  60. */
  61. m_bType = TYPE_CLASS_ALLOCATED;
  62. m_status = STATUS_SUCCESS;
  63. m_String.MaximumLength = pNewString->m_String.MaximumLength;
  64. m_String.Length = pNewString->m_String.Length;
  65. m_String.Buffer = ( PWSTR )ExAllocatePoolWithTag( PagedPool, m_String.MaximumLength, HidBattTag );
  66. if( !m_String.Buffer )
  67. {
  68. m_status = STATUS_INSUFFICIENT_RESOURCES;
  69. return;
  70. }
  71. ZeroBuffer();
  72. memcpy( m_String.Buffer, pNewString->m_String.Buffer, m_String.MaximumLength );
  73. }
  74. //
  75. // CUString::CUString( UNICODE_STRING& )
  76. //
  77. // Copy constructor for UNICODE_STRING objects
  78. //
  79. CUString :: CUString( UNICODE_STRING * NewString )
  80. {
  81. /*
  82. RtlInitUnicodeString( &m_String, NULL );
  83. m_bType = TYPE_CLASS_ALLOCATED;
  84. m_String.MaximumLength = NewString.MaximumLength + sizeof( WCHAR );
  85. m_String.Length = 0;
  86. m_String.Buffer = ( unsigned short* )ExAllocatePoolWithTag( PagedPool, m_String.MaximumLength, HidBattTag );
  87. if( !m_String.Buffer )
  88. {
  89. m_status = STATUS_INSUFFICIENT_RESOURCES;
  90. return;
  91. }
  92. RtlCopyUnicodeString( &m_String, &NewString );
  93. m_status = STATUS_SUCCESS;
  94. m_String.Buffer[ m_String.Length ] = NULL;
  95. */
  96. m_bType = TYPE_CLASS_ALLOCATED;
  97. m_status = STATUS_SUCCESS;
  98. m_String.MaximumLength = NewString->Length + sizeof( WCHAR );
  99. m_String.Length = NewString->Length;
  100. m_String.Buffer = ( PWSTR )ExAllocatePoolWithTag( PagedPool, m_String.MaximumLength, HidBattTag );
  101. if( !m_String.Buffer )
  102. {
  103. m_status = STATUS_INSUFFICIENT_RESOURCES;
  104. return;
  105. }
  106. ZeroBuffer();
  107. memcpy( m_String.Buffer, NewString->Buffer, m_String.Length );
  108. }
  109. //
  110. // CUString::CUString( PWCHAR )
  111. //
  112. // Copy constructor for WCHAR pointer objects
  113. //
  114. CUString :: CUString( PWCHAR NewString )
  115. {
  116. m_bType = TYPE_CLASS_ALLOCATED;
  117. m_status = STATUS_SUCCESS;
  118. m_String.Length = ( unsigned short )( Length( NewString ) * sizeof( WCHAR ) );
  119. m_String.MaximumLength = m_String.Length + sizeof( WCHAR );
  120. m_String.Buffer = ( PWSTR )ExAllocatePoolWithTag( PagedPool, m_String.MaximumLength, HidBattTag );
  121. if( !m_String.Buffer )
  122. {
  123. m_status = STATUS_INSUFFICIENT_RESOURCES;
  124. return;
  125. }
  126. ZeroBuffer();
  127. memcpy( m_String.Buffer, NewString, m_String.Length );
  128. }
  129. //
  130. // CUString::CUString( int )
  131. //
  132. // Constructor which creates an empty string but
  133. // allocates a string buffer of the given size of characters
  134. //
  135. CUString :: CUString( int nSize )
  136. {
  137. ASSERT( nSize >= 0 );
  138. m_bType = TYPE_CLASS_ALLOCATED;
  139. m_String.MaximumLength = 0;
  140. m_String.Length = 0;
  141. m_String.Buffer = NULL;
  142. if( nSize > 0 )
  143. {
  144. m_String.MaximumLength = (USHORT)(( nSize + 1 ) * sizeof( WCHAR ));
  145. if( nSize )
  146. {
  147. m_String.Buffer = (PWSTR)ExAllocatePoolWithTag( PagedPool, m_String.MaximumLength, HidBattTag );
  148. if( !m_String.Buffer )
  149. {
  150. m_status = STATUS_INSUFFICIENT_RESOURCES;
  151. return;
  152. }
  153. ZeroBuffer();
  154. }
  155. }
  156. m_status = STATUS_SUCCESS;
  157. }
  158. //
  159. // CUString::CUString( UNICODE_STRING& )
  160. //
  161. // Constructor with creates a string that is a representation
  162. // of the given integer and radix.
  163. //
  164. CUString :: CUString( int iVal, int iBase )
  165. {
  166. m_status = STATUS_INSUFFICIENT_RESOURCES;
  167. m_bType = TYPE_CLASS_ALLOCATED;
  168. m_String.Length = 0;
  169. m_String.MaximumLength = 0;
  170. m_String.Buffer = NULL;
  171. int iSize = 1;
  172. int iValCopy = ( !iVal ) ? 1 : iVal;
  173. while( iValCopy >= 1 )
  174. {
  175. iValCopy /= iBase;
  176. iSize++;
  177. };
  178. //
  179. // iSize is the number of digits in number, max length of string
  180. // is iSize plus the null terminator
  181. //
  182. m_String.MaximumLength = (USHORT)(( iSize + 1 ) * sizeof( WCHAR ));
  183. m_String.Buffer = (PWSTR)ExAllocatePoolWithTag( PagedPool, m_String.MaximumLength, HidBattTag );
  184. ASSERT( m_String.Buffer );
  185. if( !m_String.Buffer )
  186. {
  187. m_status = STATUS_INSUFFICIENT_RESOURCES;
  188. return;
  189. }
  190. ZeroBuffer();
  191. m_status = RtlIntegerToUnicodeString(iVal, iBase, &m_String);
  192. }
  193. //
  194. // CUString::~CUString()
  195. //
  196. // Destructor which frees the string buffer if:
  197. // 1. It exists,
  198. // and
  199. // 2. It was allocated by the class
  200. //
  201. CUString :: ~CUString()
  202. {
  203. //
  204. // If the buffer exists and was allocated by the class, free it.
  205. //
  206. if( ( m_bType == TYPE_CLASS_ALLOCATED ) && m_String.Buffer )
  207. {
  208. ExFreePool(m_String.Buffer);
  209. }
  210. }
  211. //
  212. // CUString::Append( CUString& )
  213. //
  214. // Append the given string to the object
  215. //
  216. void CUString :: Append( CUString * Append )
  217. {
  218. UNICODE_STRING NewString;
  219. //
  220. // Determine the length of the new string ( including a null ) and allocate its memory
  221. //
  222. NewString.MaximumLength = m_String.Length + Append->m_String.Length + sizeof( WCHAR );
  223. NewString.Length = 0;
  224. NewString.Buffer = (PWSTR)ExAllocatePoolWithTag( PagedPool, NewString.MaximumLength, HidBattTag );
  225. ASSERT( NewString.Buffer );
  226. //
  227. // Check for allocation failure.
  228. //
  229. if( !NewString.Buffer )
  230. {
  231. m_status = STATUS_INSUFFICIENT_RESOURCES;
  232. return;
  233. }
  234. RtlZeroMemory( NewString.Buffer, NewString.MaximumLength );
  235. //
  236. // Copy the original string into the new string
  237. //
  238. RtlCopyUnicodeString( &NewString, &m_String );
  239. //
  240. // Append the 'append' string onto the new string
  241. //
  242. NTSTATUS Status = RtlAppendUnicodeStringToString( &NewString, &Append->m_String );
  243. //
  244. // If we allocated the original string, free it
  245. //
  246. if( m_bType == TYPE_CLASS_ALLOCATED && m_String.Buffer )
  247. {
  248. ExFreePool( m_String.Buffer );
  249. }
  250. //
  251. // Copy the new string into the original strings place
  252. //
  253. m_String.MaximumLength = NewString.MaximumLength;
  254. m_String.Length = NewString.Length;
  255. m_String.Buffer = NewString.Buffer;
  256. m_bType = TYPE_CLASS_ALLOCATED;
  257. m_status = Status;
  258. }
  259. //
  260. // CUString::Append( UNICODE_STRING* )
  261. //
  262. // Append the given string to the object
  263. //
  264. void CUString :: Append( UNICODE_STRING* pAppendString )
  265. {
  266. ASSERT( pAppendString );
  267. if( !pAppendString )
  268. return;
  269. CUString AppendString( pAppendString );
  270. Append( &AppendString );
  271. }
  272. /*
  273. //
  274. // operator + ( UNICODE_STRING&, ULONG& )
  275. //
  276. CUString operator + ( UNICODE_STRING * pUCS, ULONG dwValue )
  277. {
  278. // This routine is broken for now...don't use...
  279. ASSERT( 0 );
  280. CUString ReturnString( pUCS );
  281. CUString ValueString( dwValue, 10 );
  282. ReturnString.Append( ValueString );
  283. return ReturnString;
  284. }
  285. //
  286. // operator + ( CUString&, CUString& )
  287. //
  288. CUString operator + ( CUString& l, CUString& r )
  289. {
  290. CUString ReturnString( l );
  291. ReturnString.Append( r );
  292. return ReturnString;
  293. }
  294. //
  295. // operator + ( UNICODE_STRING&, UNICODE_STRING& )
  296. //
  297. CUString operator + ( UNICODE_STRING& l, UNICODE_STRING& r )
  298. {
  299. CUString ReturnValue( l );
  300. CUString Right( r );
  301. ReturnValue.Append( Right );
  302. return ReturnValue;
  303. }
  304. */
  305. //
  306. // operator = ( CUString )
  307. //
  308. void CUString :: operator = ( CUString str )
  309. {
  310. m_String.Length = str.m_String.Length;
  311. m_String.MaximumLength = str.m_String.MaximumLength;
  312. m_String.Buffer = NULL;
  313. //
  314. // If the source string has a non-zero length buffer make a buffer of
  315. // equal size in the destination.
  316. //
  317. if( str.m_String.MaximumLength > 0 )
  318. {
  319. m_String.Buffer = (PWSTR)ExAllocatePoolWithTag( PagedPool, str.m_String.MaximumLength, HidBattTag );
  320. if( !m_String.Buffer )
  321. {
  322. m_status = STATUS_INSUFFICIENT_RESOURCES;
  323. return;
  324. }
  325. ZeroBuffer();
  326. //
  327. // If the source string has a non-zero length, copy it into the dest string.
  328. //
  329. if( str.m_String.Length > 0 )
  330. {
  331. memcpy( m_String.Buffer, str.m_String.Buffer, str.m_String.Length );
  332. }
  333. }
  334. m_bType = TYPE_CLASS_ALLOCATED;
  335. m_status = STATUS_SUCCESS;
  336. }
  337. NTSTATUS CUString :: ToCString( char** pString )
  338. {
  339. ULONG dwLength = m_String.Length >> 1;
  340. *pString = ( char* )ExAllocatePoolWithTag( PagedPool, dwLength + 1, HidBattTag );
  341. if( !*pString )
  342. return STATUS_UNSUCCESSFUL;
  343. char* pDst = *pString;
  344. char* pSrc = ( char* )m_String.Buffer;
  345. while( *pSrc )
  346. {
  347. *pDst++ = *pSrc;
  348. pSrc += sizeof( WCHAR );
  349. }
  350. *pDst = 0x0;
  351. return STATUS_SUCCESS;
  352. }
  353. void CUString :: Dump()
  354. {
  355. char* pString;
  356. ToCString( &pString );
  357. KdPrint( ( pString ) );
  358. KdPrint( ( "\n" ) );
  359. ExFreePool( pString );
  360. }
  361. ULONG CUString :: Length( PWCHAR String )
  362. {
  363. ULONG dwLength = 0;
  364. while( *String++ )
  365. {
  366. dwLength++;
  367. }
  368. return dwLength;
  369. }
  370. // the registry access class
  371. CRegistry::CRegistry(int iSize)
  372. { m_status = STATUS_INSUFFICIENT_RESOURCES;
  373. m_pTable = (PRTL_QUERY_REGISTRY_TABLE)
  374. ExAllocatePoolWithTag(NonPagedPool,sizeof(RTL_QUERY_REGISTRY_TABLE)*(iSize+1),HidBattTag);
  375. if(m_pTable)
  376. {
  377. m_status = STATUS_SUCCESS;
  378. RtlZeroMemory(m_pTable,sizeof(RTL_QUERY_REGISTRY_TABLE)*(iSize+1)); //this will terminate the table
  379. }; // appropriately
  380. };
  381. CRegistry::~CRegistry()
  382. {
  383. if (m_pTable) ExFreePool(m_pTable);
  384. };
  385. BOOL CRegistry::QueryDirect(CUString *location,CUString *key, void **pReceiveBuffer, ULONG uType)
  386. {
  387. ULONG zero = 0;
  388. m_pTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  389. m_pTable[0].Name = key->m_String.Buffer;
  390. m_pTable[0].EntryContext = *pReceiveBuffer;
  391. m_pTable[0].DefaultType = uType;
  392. m_pTable[0].DefaultData = &zero;
  393. m_pTable[0].DefaultLength = sizeof(ULONG); // there must be something here, but we need to know what...
  394. KdPrint( ( "RegClass QueryDirect: to retrieve Reg name...\n" ) );
  395. location->Dump();
  396. key->Dump();
  397. if (STATUS_SUCCESS!=
  398. RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,location->m_String.Buffer,m_pTable,NULL,NULL))
  399. return FALSE;
  400. return TRUE;
  401. };
  402. /*NTSTATUS CRegistry::QueryMustExist( CUString* pwzLocation, CUString* pwzKey, void **pReceiveBuffer )
  403. {
  404. m_pTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND | RTL_QUERY_REGISTRY_REQUIRED;
  405. m_pTable[0].Name = pwzKey->m_String.Buffer;
  406. m_pTable[0].EntryContext = *pReceiveBuffer;
  407. KdPrint( ( "RegClass QueryMustExist(): to retriee Reg name...\n" ) );
  408. pwzLocation->Dump();
  409. pwzKey->Dump();
  410. return RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, pwzLocation->m_String.Buffer, m_pTable, NULL, NULL );
  411. }
  412. */
  413. BOOL CRegistry::QueryWithCallback(PRTL_QUERY_REGISTRY_ROUTINE callback,ULONG RelativeTo,PWSTR Path,PVOID Context, PVOID Environment)
  414. {
  415. m_pTable[0].QueryRoutine = callback;
  416. m_pTable[0].Name = NULL;
  417. m_status = RtlQueryRegistryValues(RelativeTo|RTL_REGISTRY_OPTIONAL,Path,m_pTable,Context,Environment);
  418. return NT_SUCCESS(m_status);
  419. };
  420. BOOL CRegistry::WriteString(ULONG relativeTo, CUString *pBuffer, CUString *pPath, CUString *pKey)
  421. {
  422. return NT_SUCCESS(RtlWriteRegistryValue(relativeTo, pPath->GetString(), pKey->GetString(),REG_SZ,pBuffer->GetString(),pBuffer->GetLength()+sizeof(UNICODE_NULL)));
  423. };
  424. BOOL CRegistry::WriteDWord(ULONG relativeTo, void *pBuffer,CUString *pPath,CUString *pKey)
  425. {
  426. return NT_SUCCESS(RtlWriteRegistryValue(relativeTo, pPath->GetString(), pKey->GetString(),REG_DWORD,pBuffer,sizeof(REG_DWORD)));
  427. };
  428. NTSTATUS CRegistry::zwOpenKey(HANDLE * pKeyHandle,HANDLE hRoot,ACCESS_MASK DesiredAccess,CUString * pPath)
  429. {
  430. OBJECT_ATTRIBUTES ThisObject;
  431. NTSTATUS status;
  432. CUString ThisNull(NULL);
  433. // setup target object for call
  434. InitializeObjectAttributes( &ThisObject,
  435. &(pPath->m_String),
  436. OBJ_CASE_INSENSITIVE,
  437. hRoot,
  438. NULL);
  439. KdPrint( ( "RESMAN: Opening registry key: " ) );
  440. pPath->Dump();
  441. status = ZwOpenKey( pKeyHandle,
  442. DesiredAccess,
  443. &ThisObject );
  444. return status;
  445. }
  446. /*
  447. NTSTATUS CRegistry::DeleteKey(HANDLE hTheKey)
  448. {
  449. return ZwDeleteKey(hTheKey);
  450. }
  451. */
  452. NTSTATUS CRegistry::zwCreateKey(HANDLE * pKeyHandle,HANDLE hRoot,ACCESS_MASK DesiredAccess,CUString * pPath,ULONG CreateOptions)
  453. {
  454. OBJECT_ATTRIBUTES ThisObject;
  455. NTSTATUS status;
  456. // setup target object for call
  457. InitializeObjectAttributes( &ThisObject,
  458. &(pPath->m_String),
  459. OBJ_CASE_INSENSITIVE,
  460. hRoot,
  461. NULL);
  462. KdPrint( ( "RESMAN: Creating registry key: " ) );
  463. pPath->Dump();
  464. status = ZwCreateKey(pKeyHandle,
  465. DesiredAccess,
  466. &ThisObject,
  467. 0,
  468. NULL,
  469. CreateOptions,
  470. (ULONG*)&m_lDisposition);
  471. return status;
  472. }
  473. BOOL CRegistry::zwCloseKey(HANDLE TheKey)
  474. {
  475. return NT_SUCCESS(ZwClose(TheKey));
  476. }
  477. NTSTATUS CRegistry::zwWriteValue(HANDLE hTheKey,CUString * ValueName,ULONG lType,PVOID pData,ULONG lSize)
  478. {
  479. NTSTATUS status;
  480. status = ZwSetValueKey(hTheKey,
  481. &ValueName->m_String,
  482. 0,
  483. lType,
  484. pData,
  485. lSize);
  486. return status;
  487. }
  488. NTSTATUS CRegistry::CheckKey(ULONG RelativeTo ,PUNICODE_STRING puRegKey)
  489. {
  490. // return (RtlCheckRegistryKey( RelativeTo,(PWSTR)puRegKey));
  491. return FALSE;
  492. }
  493. // error logging methods
  494. /*
  495. CErrorLogEntry::CErrorLogEntry(PVOID pSource, ULONG errorCode, USHORT dumpDataSize, ULONG uniqueErrorValue,
  496. NTSTATUS status, ULONG *dumpData, UCHAR FunctionCode)
  497. {
  498. m_pPacket = (PIO_ERROR_LOG_PACKET)
  499. IoAllocateErrorLogEntry(pSource, (UCHAR) (sizeof(IO_ERROR_LOG_PACKET)+
  500. (dumpDataSize * sizeof(ULONG))));
  501. if (!m_pPacket) return;
  502. int i;
  503. m_pPacket->ErrorCode = errorCode;
  504. m_pPacket->DumpDataSize = dumpDataSize * sizeof(ULONG);
  505. m_pPacket->SequenceNumber = 0;
  506. m_pPacket->MajorFunctionCode = FunctionCode;
  507. m_pPacket->IoControlCode = 0;
  508. m_pPacket->RetryCount = 0;
  509. m_pPacket->UniqueErrorValue = uniqueErrorValue;
  510. m_pPacket->FinalStatus = status;
  511. for (i = 0; i < dumpDataSize; i++)
  512. m_pPacket->DumpData[i] = dumpData[i];
  513. IoWriteErrorLogEntry(m_pPacket);
  514. };
  515. CErrorLogEntry::~CErrorLogEntry()
  516. {
  517. };
  518. */