Leaked source code of windows server 2003
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.

551 lines
17 KiB

  1. //
  2. // PCH.H
  3. //
  4. // Copyright (C) Microsoft Corporation, 1995-1996
  5. //
  6. #ifndef _REGPRIV_
  7. #define _REGPRIV_
  8. // Conditional enable registry "features" based on the target model.
  9. //
  10. // WANT_STATIC_KEYS: Allocates key handles from a memory pool allocated
  11. // during library initialization. Especially useful for real-mode to reduce
  12. // the memory fragmentation caused by allocating several small fixed objects.
  13. //
  14. // WANT_FULL_MEMORY_CLEANUP: When detaching, free every memory block. Not
  15. // necessary for the ring zero version where "detach" means system shutdown.
  16. //
  17. // WANT_HIVE_SUPPORT: RegLoadKey, RegUnLoadKey, RegSaveKey, RegReplaceKey
  18. // APIs plus support code.
  19. //
  20. // WANT_DYNKEY_SUPPORT: RegCreateDynKey plus HKEY_DYN_DATA support.
  21. //
  22. // WANT_NOTIFY_CHANGE_SUPPORT: RegNotifyChangeKeyValue plus support code.
  23. #ifndef IS_32
  24. #define WANT_STATIC_KEYS
  25. #endif
  26. #ifndef VXD
  27. #define WANT_FULL_MEMORY_CLEANUP
  28. #endif
  29. #ifndef REALMODE
  30. #define WANT_HIVE_SUPPORT
  31. #endif
  32. #ifdef VXD
  33. #define WANT_REGREPLACEKEY
  34. #define WANT_DYNKEY_SUPPORT
  35. #define WANT_NOTIFY_CHANGE_SUPPORT
  36. #endif
  37. // Map any other header's definitions of these to unused types.
  38. #define HKEY __UNUSED_HKEY
  39. #define LPHKEY __UNUSED_LPHKEY
  40. #ifndef WIN32_LEAN_AND_MEAN
  41. #define WIN32_LEAN_AND_MEAN
  42. #endif
  43. #define NORESOURCE // prevent RT_* definitions from vmmsys.h
  44. #include <windows.h>
  45. #include <string.h>
  46. #ifdef VXD
  47. #error "Cannot compile with VXD defined"
  48. // #include <vmmsys.h>
  49. // #include <thrdsys.h>
  50. #endif
  51. #ifndef UNALIGNED
  52. #define UNALIGNED // defined in standard headers for RISC
  53. #endif
  54. #ifndef ANYSIZE_ARRAY
  55. #define ANYSIZE_ARRAY 1
  56. #endif
  57. #ifdef VXD
  58. // By default, all registry code and data is pageable.
  59. #pragma VMM_PAGEABLE_CODE_SEG
  60. #pragma VMM_PAGEABLE_DATA_SEG
  61. #endif
  62. #define UNREFERENCED_PARAMETER(P) (P)
  63. #define INTERNAL PASCAL NEAR
  64. #define INTERNALV CDECL NEAR
  65. // Undefine any constants that we're about to define ourselves.
  66. #undef HKEY
  67. #undef LPHKEY
  68. #undef HKEY_CLASSES_ROOT
  69. #undef HKEY_CURRENT_USER
  70. #undef HKEY_LOCAL_MACHINE
  71. #undef HKEY_USERS
  72. #undef HKEY_PERFORMANCE_DATA
  73. #undef HKEY_CURRENT_CONFIG
  74. #undef HKEY_DYN_DATA
  75. typedef struct _KEY FAR* HKEY; // Forward reference
  76. #include "regdebug.h"
  77. #include "regffmt.h"
  78. #include "regfinfo.h"
  79. // Many file structures in the registry are declared as DWORDs, the HIWORD is
  80. // always zero. Use SmallDword to access such DWORDs for optimal access in
  81. // 16-bit or 32-bit code.
  82. #if defined(IS_32)
  83. #define SmallDword(dw) ((UINT) (dw))
  84. #else
  85. #define SmallDword(dw) ((UINT) LOWORD((dw)))
  86. #endif
  87. #if defined(WIN16)
  88. #define IsNullPtr(ptr) (SELECTOROF((ptr)) == NULL)
  89. #else
  90. #define IsNullPtr(ptr) ((ptr) == NULL)
  91. #endif
  92. // In either mode, the resulting code uses an instrinsic version of the memcmp
  93. // function.
  94. #if defined(IS_32)
  95. #define CompareMemory memcmp
  96. #else
  97. #define CompareMemory _fmemcmp
  98. #endif
  99. #if defined(WIN16) || defined(WIN32)
  100. #define StrCpy(lpd, lps) (lstrcpy((lpd), (lps)))
  101. #define StrCpyN(lpd, lps, cb) (lstrcpyn((lpd), (lps), (cb)))
  102. #define StrLen(lpstr) (lstrlen((lpstr)))
  103. #define ToUpper(ch) ((int) (DWORD) AnsiUpper((LPSTR)((BYTE)(ch))))
  104. #define RgCreateFile(lpfn) ((HFILE) _lcreat((lpfn), 0))
  105. #define RgOpenFile(lpfn, mode) ((HFILE) _lopen((lpfn), (mode)))
  106. #define RgCloseFile(h) ((VOID) _lclose(h))
  107. #if defined(WIN32)
  108. #define RgDeleteFile(lpv) (DeleteFile((lpv)))
  109. #define RgRenameFile(lpv1, lpv2) (MoveFile((lpv1), (lpv2)))
  110. #define RgGetFileAttributes(lpv) (GetFileAttributes((lpv)))
  111. #define RgSetFileAttributes(lpv, a) (SetFileAttributes((lpv), (a)))
  112. #define RgCommitFile(h) (FlushFileBuffers((HANDLE)h))
  113. #ifdef USEHEAP
  114. extern HANDLE g_RgHeap; // Low memory heap for testing
  115. #define AllocBytes(cb) ((LPVOID) HeapAlloc(g_RgHeap, 0, (cb)))
  116. #define FreeBytes(lpv) ((VOID) HeapFree(g_RgHeap, 0, (lpv)))
  117. #define ReAllocBytes(lpv, cb) ((LPVOID) HeapReAlloc(g_RgHeap, 0, (lpv), (cb)))
  118. #define MemorySize(lpv) ((UINT) HeapSize(g_RgHeap, 0, (lpv)))
  119. #else
  120. #define AllocBytes(cb) ((LPVOID) LocalAlloc(LMEM_FIXED, (cb)))
  121. #define FreeBytes(lpv) ((VOID) LocalFree((HLOCAL) (lpv)))
  122. #define ReAllocBytes(lpv, cb) ((LPVOID) LocalReAlloc((HLOCAL) (lpv), (cb), LMEM_MOVEABLE))
  123. #define MemorySize(lpv) ((UINT) LocalSize((lpv)))
  124. #endif // USEHEAP
  125. #else
  126. #define AllocBytes(cb) ((LPVOID) MAKELP(GlobalAlloc(GMEM_FIXED, (cb)), 0))
  127. #define FreeBytes(lpv) ((VOID) GlobalFree((HGLOBAL) SELECTOROF((lpv))))
  128. #define ReAllocBytes(lpv, cb) ((LPVOID) MAKELP(GlobalReAlloc((HGLOBAL) SELECTOROF((lpv)), (cb), GMEM_MOVEABLE), 0))
  129. #define MemorySize(lpv) ((UINT) GlobalSize((HGLOBAL) SELECTOROF((lpv))))
  130. // WIN16's ZeroMemory/MoveMemory: SETUPX is the only target WIN16 environment
  131. // and they already use _fmemset and _fmemmove, so just use their versions.
  132. #define ZeroMemory(lpv, cb) (_fmemset((lpv), 0, (cb)))
  133. #define MoveMemory(lpd, lps, cb) (_fmemmove((lpd), (lps), (cb)))
  134. #endif // WIN16 || WIN32
  135. #elif defined(REALMODE)
  136. #define IsBadStringPtr(lpv, cb) (FALSE)
  137. #define IsBadHugeWritePtr(lpv, cb) (FALSE)
  138. #define IsBadHugeReadPtr(lpv, cb) (FALSE)
  139. #define StrCpy(lpd, lps) (_fstrcpy((lpd), (lps)))
  140. #define StrCpyN(lpd, lps, cb) (_fstrcpyn((lpd), (lps), (cb)))
  141. #define StrLen(lpstr) (_fstrlen((lpstr)))
  142. #define ToUpper(ch) ((int)(((ch>='a')&&(ch<='z'))?(ch-'a'+'A'):ch))
  143. LPVOID INTERNAL AllocBytes(UINT);
  144. VOID INTERNAL FreeBytes(LPVOID);
  145. LPVOID INTERNAL ReAllocBytes(LPVOID, UINT);
  146. UINT INTERNAL MemorySize(LPVOID);
  147. VOID INTERNAL ZeroMemory(LPVOID, UINT);
  148. VOID INTERNAL MoveMemory(LPVOID, const VOID FAR*, UINT);
  149. #elif defined(VXD)
  150. #undef IsBadStringPtr // Conflicts with windows.h
  151. #undef ZeroMemory // Conflicts with windows.h
  152. #undef MoveMemory // Conflicts with windows.h
  153. BOOL INTERNAL RgIsBadStringPtr(const VOID FAR*, UINT);
  154. BOOL INTERNAL RgIsBadOptionalStringPtr(const VOID FAR*, UINT);
  155. BOOL INTERNAL RgIsBadHugeWritePtr(const VOID FAR*, UINT);
  156. BOOL INTERNAL RgIsBadHugeOptionalWritePtr(const VOID FAR*, UINT);
  157. BOOL INTERNAL RgIsBadHugeReadPtr(const VOID FAR*, UINT);
  158. #define IsBadStringPtr(lpv, cb) (RgIsBadStringPtr((lpv), (cb)))
  159. #define IsBadOptionalStringPtr(lpv, cb) (RgIsBadOptionalStringPtr((lpv), (cb)))
  160. #define IsBadHugeWritePtr(lpv, cb) (RgIsBadHugeWritePtr((lpv), (cb)))
  161. #define IsBadHugeOptionalWritePtr(lpv, cb) (RgIsBadHugeOptionalWritePtr((lpv), (cb)))
  162. #define IsBadHugeReadPtr(lpv, cb) (RgIsBadHugeReadPtr((lpv), (cb)))
  163. #define StrCpy(lpd, lps) (_lstrcpyn((PCHAR)(lpd), (PCHAR)(lps), (ULONG)(-1)))
  164. #define StrCpyN(lpd, lps, cb) (_lstrcpyn((PCHAR)(lpd), (PCHAR)(lps), (ULONG)(cb)))
  165. #define StrLen(lpstr) (_lstrlen((PCHAR)(lpstr)))
  166. extern UCHAR UpperCaseTable[256];
  167. #define ToUpper(ch) ((int)(UpperCaseTable[(UCHAR)(ch)]))
  168. VOID INTERNAL RgSetAndReleaseEvent(HANDLE hEvent);
  169. #define RgGetCurrentThreadId() ((DWORD)pthcbCur)
  170. #define AllocBytes(cb) ((LPVOID) _HeapAllocate((cb), HEAPSWAP))
  171. #define FreeBytes(lpv) ((VOID) _HeapFree((lpv), 0))
  172. #define ReAllocBytes(lpv, cb) ((LPVOID) _HeapReAllocate((lpv), (cb), HEAPSWAP))
  173. #define MemorySize(lpv) ((UINT) _HeapGetSize((lpv), 0))
  174. #define AllocPages(cp) ((LPVOID) _PageAllocate((cp), PG_SYS, 0, 0, 0, 0, NULL, 0))
  175. #define FreePages(lpv) ((VOID) _PageFree((ULONG) (lpv), 0))
  176. #define ReAllocPages(lpv, cp) ((LPVOID) _PageReAllocate((ULONG) (lpv), (cp), 0))
  177. VOID INTERNAL RgZeroMemory(LPVOID, UINT);
  178. VOID INTERNAL RgMoveMemory(LPVOID, const VOID FAR*, UINT);
  179. #define ZeroMemory RgZeroMemory
  180. #define MoveMemory RgMoveMemory
  181. #else
  182. #error Must define REALMODE, VXD, WIN16, or WIN32.
  183. #endif
  184. // The IsBadHugeOptional*Ptr macros are used to validate pointers that may be
  185. // NULL. By wrapping this "predicate", we can generate smaller code in some
  186. // environments, specifically VMM...
  187. #if !defined(VXD)
  188. #define IsBadOptionalStringPtr(lpv, cb) \
  189. (!IsNullPtr((lpv)) && IsBadStringPtr((lpv), (cb)))
  190. #define IsBadHugeOptionalWritePtr(lpv, cb) \
  191. (!IsNullPtr((lpv)) && IsBadHugeWritePtr((lpv), (cb)))
  192. #endif
  193. // The IsEnumIndexTooBig macro is used to check if a DWORD sized index can fit
  194. // into a UINT sized variable. Only useful for validation of RegEnumKey or
  195. // RegEnumValue to make small code in both 16 and 32 bit environments.
  196. #if defined(IS_32)
  197. #define IsEnumIndexTooBig(index) (FALSE)
  198. #else
  199. #define IsEnumIndexTooBig(index) (HIWORD(index) > 0)
  200. #endif
  201. #if defined(VXD)
  202. BOOL INTERNAL RgLockRegistry(VOID);
  203. VOID INTERNAL RgUnlockRegistry(VOID);
  204. VOID INTERNAL RgDelayFlush(VOID);
  205. VOID INTERNAL RgYield(VOID);
  206. #else
  207. #define RgLockRegistry() (TRUE)
  208. #define RgUnlockRegistry() (TRUE)
  209. #define RgDelayFlush() (TRUE)
  210. #define RgYield() (TRUE)
  211. #endif
  212. // Eliminate the need for #ifdef DBCS by using macros and letting the compiler
  213. // optimize out the DBCS code on SBCS systems.
  214. #ifdef DBCS
  215. #if !defined(WIN16) && !defined(WIN32)
  216. BOOL INTERNAL RgIsDBCSLeadByte(BYTE TestChar);
  217. #define IsDBCSLeadByte(ch) RgIsDBCSLeadByte(ch)
  218. #endif
  219. #else
  220. #define IsDBCSLeadByte(ch) ((ch), FALSE)
  221. #endif // DBCS
  222. #ifdef WANT_DYNKEY_SUPPORT
  223. // Internally used for maintaining dynamic key information; only keeps the
  224. // fields that we actually need from the REG_PROVIDER structure given to
  225. // VMMRegCreateDynKey.
  226. typedef struct _INTERNAL_PROVIDER {
  227. PQUERYHANDLER ipi_R0_1val;
  228. PQUERYHANDLER ipi_R0_allvals;
  229. LPVOID ipi_key_context;
  230. } INTERNAL_PROVIDER, FAR* PINTERNAL_PROVIDER;
  231. #endif
  232. typedef struct _KEY {
  233. WORD Signature; // KEY_SIGNATURE
  234. WORD Flags; // KEYF_* bits
  235. UINT ReferenceCount;
  236. LPFILE_INFO lpFileInfo;
  237. DWORD KeynodeIndex;
  238. DWORD ChildKeynodeIndex;
  239. WORD BlockIndex;
  240. WORD BigKeyLockedBlockIndex; // If a bigkey function locked a datablock, this is its index
  241. BYTE KeyRecordIndex;
  242. BYTE PredefinedKeyIndex;
  243. struct _KEY FAR* lpNext;
  244. struct _KEY FAR* lpPrev;
  245. UINT LastEnumKeyIndex;
  246. DWORD LastEnumKeyKeynodeIndex;
  247. #ifdef WANT_DYNKEY_SUPPORT
  248. PINTERNAL_PROVIDER pProvider;
  249. #endif
  250. } KEY;
  251. #define KEY_SIGNATURE 0x4B48 // "HK"
  252. #define KEYF_PREDEFINED 0x01 // Represents one of HKEY_*
  253. #define KEYF_DELETED 0x02 //
  254. #define KEYF_INVALID 0x04 //
  255. #define KEYF_STATIC 0x08 // Allocated from static pool
  256. #define KEYF_ENUMKEYCACHED 0x10 // LastEnumKey* values valid
  257. #define KEYF_HIVESALLOWED 0x20 //
  258. #define KEYF_PROVIDERHASVALUELENGTH 0x40 // PROVIDER_KEEPS_VALUE_LENGTH
  259. #define KEYF_NEVERDELETE 0x80 // Reference count overflow
  260. #define KEYF_BIGKEYROOT 0x100 // This key handle is for a big key
  261. #define KEYF_ENUMEXTENTCACHED 0x200 // LastEnumKey* is for a big key extent
  262. #define INDEX_CLASSES_ROOT 0
  263. #define INDEX_CURRENT_USER 1
  264. #define INDEX_LOCAL_MACHINE 2
  265. #define INDEX_USERS 3
  266. #define INDEX_PERFORMANCE_DATA 4
  267. #define INDEX_CURRENT_CONFIG 5
  268. #define INDEX_DYN_DATA 6
  269. // Returns TRUE if the KEY references the root of a hive, such as
  270. // HKEY_LOCAL_MACHINE, HKEY_USERS, or any hive loaded by RegLoadKey.
  271. #define IsKeyRootOfHive(hkey) \
  272. ((hkey)-> KeynodeIndex == (hkey)-> lpFileInfo-> KeynodeHeader.RootIndex)
  273. // Returns TRUE if the KEY is a subkey of HKEY_DYN_DATA.
  274. #ifdef WANT_DYNKEY_SUPPORT
  275. #define IsDynDataKey(hkey) \
  276. ((hkey)-> PredefinedKeyIndex == INDEX_DYN_DATA)
  277. #else
  278. #define IsDynDataKey(hkey) (FALSE)
  279. #endif
  280. #include <regapix.h>
  281. #include "regkylst.h"
  282. #include "regdblk.h"
  283. #include "regknode.h"
  284. #include "regnckey.h"
  285. #include "regfsio.h"
  286. #include "regmem.h"
  287. #define ERROR_BIGKEY_NEEDED 1025L // Internal error, the data won't fit in a normal key
  288. #ifdef VXD
  289. extern BYTE g_RgPostCriticalInit;
  290. extern BYTE g_RgFileAccessDisabled;
  291. #define IsPostCriticalInit() (g_RgPostCriticalInit)
  292. #define IsFileAccessDisabled() (g_RgFileAccessDisabled)
  293. #else
  294. #define IsPostCriticalInit() (TRUE)
  295. #define IsFileAccessDisabled() (FALSE)
  296. #endif
  297. // g_RgWorkBuffer: one buffer is always available of size SIZEOF_WORK_BUFFER.
  298. // These macros wrap access to this buffer for to verify only one routine is
  299. // attempting to use it at any time.
  300. extern LPVOID g_RgWorkBuffer;
  301. #ifdef DEBUG
  302. extern BOOL g_RgWorkBufferBusy;
  303. #define RgLockWorkBuffer() \
  304. (ASSERT(!g_RgWorkBufferBusy), g_RgWorkBufferBusy = TRUE, (LPVOID) g_RgWorkBuffer)
  305. #define RgUnlockWorkBuffer(lpv) \
  306. (VOID) (ASSERT((lpv) == g_RgWorkBuffer), g_RgWorkBufferBusy = FALSE)
  307. #else
  308. #define RgLockWorkBuffer() ((LPVOID) g_RgWorkBuffer)
  309. #define RgUnlockWorkBuffer(lpv)
  310. #endif
  311. #define SIZEOF_WORK_BUFFER (sizeof(W95KEYNODE_BLOCK))
  312. #define IsKeyRecordFree(lpkr) \
  313. (((lpkr)-> DatablockAddress) == REG_NULL)
  314. BOOL
  315. INTERNAL
  316. RgIsBadSubKey(
  317. LPCSTR lpSubKey
  318. );
  319. UINT
  320. INTERNAL
  321. RgGetNextSubSubKey(
  322. LPCSTR lpSubKey,
  323. LPCSTR FAR* lplpSubSubKey,
  324. UINT FAR* lpSubSubKeyLength
  325. );
  326. #define LK_OPEN 0x0000 // Open key only
  327. #define LK_CREATE 0x0001 // Create or open key
  328. #define LK_CREATEDYNDATA 0x0002 // HKEY_DYN_DATA may create
  329. #define LK_BIGKEYEXT 0x0004 // Search only for big key extents
  330. int
  331. INTERNAL
  332. RgLookupKey(
  333. HKEY hKey,
  334. LPCSTR lpSubKey,
  335. LPHKEY lphSubKey,
  336. UINT Flags
  337. );
  338. int
  339. INTERNAL
  340. RgCreateOrOpenKey(
  341. HKEY hKey,
  342. LPCSTR lpSubKey,
  343. LPHKEY lphKey,
  344. UINT Flags
  345. );
  346. int
  347. INTERNAL
  348. RgLookupKeyByIndex(
  349. HKEY hKey,
  350. UINT Index,
  351. LPSTR lpKeyName,
  352. LPDWORD lpcbKeyName,
  353. UINT Flags
  354. );
  355. int
  356. INTERNAL
  357. RgLookupValueByName(
  358. HKEY hKey,
  359. LPCSTR lpValueName,
  360. LPKEY_RECORD FAR* lplpKeyRecord,
  361. LPVALUE_RECORD FAR* lplpValueRecord
  362. );
  363. int
  364. INTERNAL
  365. RgLookupValueByNameStd(
  366. HKEY hKey,
  367. LPCSTR lpValueName,
  368. LPKEY_RECORD FAR* lplpKeyRecord,
  369. LPVALUE_RECORD FAR* lplpValueRecord
  370. );
  371. int
  372. INTERNAL
  373. RgLookupValueByIndex(
  374. HKEY hKey,
  375. UINT Index,
  376. LPVALUE_RECORD FAR* lplpValueRecord
  377. );
  378. int
  379. INTERNAL
  380. RgLookupValueByIndexStd(
  381. HKEY hKey,
  382. UINT Index,
  383. LPVALUE_RECORD FAR* lplpValueRecord,
  384. UINT FAR* lpValueCount
  385. );
  386. int
  387. INTERNAL
  388. RgCopyFromValueRecord(
  389. HKEY hKey,
  390. LPVALUE_RECORD lpValueRecord,
  391. LPSTR lpValueName,
  392. LPDWORD lpcbValueName,
  393. LPDWORD lpType,
  394. LPBYTE lpData,
  395. LPDWORD lpcbData
  396. );
  397. VOID
  398. INTERNAL
  399. RgDeleteValueRecord(
  400. LPKEY_RECORD lpKeyRecord,
  401. LPVALUE_RECORD lpValueRecord
  402. );
  403. int
  404. INTERNAL
  405. RgReAllocKeyRecord(
  406. HKEY hKey,
  407. DWORD Length,
  408. LPKEY_RECORD FAR* lplpKeyRecord
  409. );
  410. int
  411. INTERNAL
  412. RgSetValue(
  413. HKEY hKey,
  414. LPCSTR lpValueName,
  415. DWORD Type,
  416. LPBYTE lpData,
  417. UINT cbData
  418. );
  419. int
  420. INTERNAL
  421. RgSetValueStd(
  422. HKEY hKey,
  423. LPCSTR lpValueName,
  424. DWORD Type,
  425. LPBYTE lpData,
  426. UINT cbData,
  427. BOOL fBigKeyExtent
  428. );
  429. int
  430. INTERNAL
  431. RgDeleteKey(
  432. HKEY hKey
  433. );
  434. DWORD
  435. INTERNAL
  436. RgChecksum(
  437. LPVOID lpBuffer,
  438. UINT ByteCount
  439. );
  440. DWORD
  441. INTERNAL
  442. RgHashString(
  443. LPCSTR lpString,
  444. UINT Length
  445. );
  446. WORD
  447. INTERNAL
  448. RgAtoW(
  449. LPCSTR lpDec
  450. );
  451. VOID
  452. INTERNAL
  453. RgWtoA(
  454. WORD Dec,
  455. LPSTR lpDec
  456. );
  457. int
  458. INTERNAL
  459. RgStrCmpNI(
  460. LPCSTR lpString1,
  461. LPCSTR lpString2,
  462. UINT Length
  463. );
  464. int
  465. INTERNAL
  466. RgCopyFileBytes(
  467. HFILE hSourceFile,
  468. LONG SourceOffset,
  469. HFILE hDestinationFile,
  470. LONG DestinationOffset,
  471. DWORD cbSize
  472. );
  473. BOOL
  474. INTERNAL
  475. RgGenerateAltFileName(
  476. LPCSTR lpFileName,
  477. LPSTR lpAltFileName,
  478. char ExtensionChar
  479. );
  480. int
  481. INTERNAL
  482. RgCopyFile(
  483. LPCSTR lpSourceFile,
  484. LPCSTR lpDestinationFile
  485. );
  486. int
  487. INTERNAL
  488. RgReplaceFileInfo(
  489. LPFILE_INFO lpFileInfo
  490. );
  491. #endif // _REGPRIV_