📄 iorm.c
字号:
// look for the resource domain structure
for (pdom = g_DomainList, pdomPrevious = NULL; pdom; pdomPrevious = pdom, pdom = pdom->pNext) {
if (pdom->dwResId == dwResId) {
break; // found a match, exit the loop
}
}
if(pdom == NULL) {
dwError = ERROR_FILE_NOT_FOUND;
goto done; // no such resource
}
// handle deletion differently for dense and sparse tables
if (pdom->table.dwSize <= gdwMaxDenseResources) {
// make sure nobody is using the resources
DWORD dwTrav = 0;
DenseTable *ptab = &pdom->table.dt;
for(dwTrav = 0; dwTrav < pdom->table.dwSize; dwTrav++) {
if(ptab->pUseCount[dwTrav] != 0
&& RBMIsSet(ptab->dwResMax, dwTrav, ptab->prvValid)) {
dwError = ERROR_BUSY;
break;
}
}
} else {
// deallocate the list of free ranges -- we don't keep track
// of which non-free resources have already been handed out.
SparseTableNode *pnode = pdom->table.st.pFirst;
while(pnode != NULL) {
SparseTableNode *pNext = pnode->pNext;
LocalFree(pnode);
pnode = pNext;
}
}
// can we delete the entry?
if(dwError == ERROR_SUCCESS) {
// yes, remove it from the list and free it
if(pdomPrevious != NULL) {
DEBUGCHK(pdomPrevious->pNext == pdom);
pdomPrevious->pNext = pdom->pNext;
} else {
g_DomainList = pdom->pNext;
}
LocalFree(pdom);
}
done:
; // need this to keep the compiler happy
}
__except(EXCEPTION_EXECUTE_HANDLER) {
dwError = ERROR_GEN_FAILURE;
}
LeaveCriticalSection(&gcsIORM);
if(dwError != ERROR_SUCCESS) {
SetLastError(dwError);
fOk = FALSE;
} else {
fOk = TRUE;
}
DEBUGMSG(!fOk && (ZONE_WARNING || ZONE_RESMGR),
(_T("IORM: destruction of list id 0x%08x returned %d, error code %d\r\n"),
dwResId, fOk, dwError));
return fOk;
}
// Parse a registry key to set up initially available resources
// Looks like:
// ResourceName\
// "Identifier"=dword:1
// "Minimum"=dword:1
// "Space"=dword:16
// "Ranges"="1-15"
// "Shared"="5,7-9"
static BOOL ScanRange (WCHAR **ps, DWORD *a, DWORD *b)
{
if (**ps == L'\0')
return FALSE; // end of string
*a = wcstoul(*ps, ps, 0);
if (**ps == L'-')
*b = wcstoul(*ps+1, ps, 0);
else
*b = *a;
if (*b < *a)
return FALSE; // invalid range
else
*b -= *a - 1; // turn it into a length
// incr past the comma (if present) and make
// sure the char after the comma is not \0.
// it's ok for **ps to be \0 imm after a conversion.
if (**ps == L'\0' || **ps == L',' && *++*ps != L'\0')
return TRUE;
return FALSE; // malformed range
}
static void ResourceInitFromKey (HKEY hk)
{
DWORD valsz, rsz;
WCHAR *valbuf, *p;
DWORD a[3]; // no Resource API takes more than 3 parms
if (RegQueryInfoKey(hk, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &valsz, NULL, NULL) != ERROR_SUCCESS)
return;
__try {
valbuf = alloca(valsz);
}
__except(EXCEPTION_EXECUTE_HANDLER) {
valbuf = NULL;
}
// create a default
if (valbuf == NULL ||
RegQueryValueEx(hk, L"Identifier", NULL, NULL, (PBYTE)&a[0], ((rsz = sizeof(DWORD)), &rsz)) != ERROR_SUCCESS ||
RegQueryValueEx(hk, L"Minimum", NULL, NULL, (PBYTE)&a[1], ((rsz = sizeof(DWORD)), &rsz)) != ERROR_SUCCESS ||
RegQueryValueEx(hk, L"Space", NULL, NULL, (PBYTE)&a[2], ((rsz = sizeof(DWORD)), &rsz)) != ERROR_SUCCESS ||
IORM_ResourceCreateList(a[0], a[1], a[2]) == FALSE) {
return;
}
// initialize resources based on the registry
if (RegQueryValueEx(hk, L"Ranges", NULL, NULL, (PBYTE)valbuf, ((rsz = valsz), &rsz)) == ERROR_SUCCESS) {
p = valbuf;
while (ScanRange(&p, &a[1], &a[2]))
IORM_ResourceAdjust(a[0], a[1], a[2], FALSE); // mark ranges as valid
}
if (RegQueryValueEx(hk, L"Shared", NULL, NULL, (PBYTE)valbuf, ((rsz = valsz), &rsz)) == ERROR_SUCCESS) {
p = valbuf;
while (ScanRange(&p, &a[1], &a[2])) {
BOOL fOk = IORM_ResourceMarkAsShareable(a[0], a[1], a[2], TRUE);
DEBUGCHK(fOk);
}
}
}
void ResourceInitFromRegistry (LPCTSTR key)
{
HKEY hk, hk2;
WCHAR *sknm;
DWORD i, sksz, rsz;
DEBUGCHK( key != NULL ); // not a published API so no need for a retail runtime check
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, 0, &hk) != ERROR_SUCCESS ||
RegQueryInfoKey(hk, NULL, NULL, NULL, NULL, &sksz, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
return;
// get the max table size
sksz = sizeof(i);
if(RegQueryValueEx(hk, _T("MaxDenseResources"), NULL, NULL, (LPBYTE) &i, &sksz) == ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT, (_T("ResourceInitFromRegistry: max resources set to %d\r\n"),
gdwMaxDenseResources));
gdwMaxDenseResources = i;
}
sksz += 1; // account for termination
sksz *= sizeof(*sknm); // convert to bytes
__try {
sknm = alloca(sksz);
}
__except(EXCEPTION_EXECUTE_HANDLER) {
sknm = NULL;
}
if (sknm != NULL) {
for (i=0; RegEnumKeyEx(hk, i, sknm, ((rsz = sksz), &rsz), NULL, NULL, NULL, NULL) == ERROR_SUCCESS; ++i) {
if (RegOpenKeyEx(hk, sknm, 0, 0, &hk2) == ERROR_SUCCESS) {
ResourceInitFromKey(hk2);
RegCloseKey(hk2);
}
}
}
RegCloseKey(hk);
}
// *** Must be first function called and should only be called once!
// Initializes global variables in this module.
void ResourceInitModule (void)
{
DEBUGCHK(g_DomainList == NULL); // bss data must be initted to zero by the crt
g_DomainList = NULL;
InitializeCriticalSection(&gcsIORM);
gdwMaxDenseResources = DEF_TABLE_THRESHOLD;
}
#ifdef DEBUG
#ifndef UNIT_TEST
#define OUTPUT(a) DEBUGMSG(1, a)
#else
#define OUTPUT(a) wprintf a
#endif
void ResourceDump (ResourceDomain *pdom)
{
if (pdom->table.dwSize <= gdwMaxDenseResources) {
DWORD dwVectorEntries = (pdom->table.dwSize + 31) / 32;
DWORD dwTrav;
OUTPUT((TEXT("Resource id 0x%08x has range 0x%x - 0x%x (size 0x%x (%u): DENSE)\n"),
pdom->dwResId, pdom->dwOffset, pdom->dwOffset + pdom->table.dwSize - 1,
pdom->table.dwSize, pdom->table.dwSize));
for(dwTrav = 0; dwTrav < dwVectorEntries; dwTrav++) {
DWORD dwInUse = 0;
DWORD dwBaseId = dwTrav * 32;
DWORD dwMaxId = dwBaseId + 32;
DWORD dwId;
// figure out which drivers are in use
if(dwMaxId > pdom->table.dwSize) {
dwMaxId = pdom->table.dwSize;
}
dwMaxId -= dwBaseId;
for(dwId = 0; dwId < dwMaxId; dwId++) {
if(RBMIsSet(pdom->table.dwSize, dwId + dwBaseId, pdom->table.dt.prvValid)
&& pdom->table.dt.pUseCount[dwId + dwBaseId] != 0) {
dwInUse |= (1 << dwId);
}
}
// display the status
OUTPUT((TEXT("\tValid/Allocated/Shareable/exclusive %d: 0x%08x 0x%08x 0x%08x\n"),
dwTrav, pdom->table.dt.prvValid[dwTrav], dwInUse, pdom->table.dt.prvShareable[dwTrav],
pdom->table.dt.prvExclusive[dwTrav]));
}
} else {
SparseTableNode *pnod;
OUTPUT((TEXT("Resource id 0x%08x has range 0x%08x - 0x%08x (size 0x%08x (%u): SPARSE)\n"),
pdom->dwResId, pdom->dwOffset, pdom->dwOffset + pdom->table.dwSize - 1,
pdom->table.dwSize, pdom->table.dwSize));
OUTPUT((TEXT("\tAvailable resources:")));
pnod = pdom->table.st.pFirst;
if (pnod == NULL) OUTPUT((TEXT(" *none*")));
while (pnod) {
if (pnod->res.len == 0) OUTPUT((TEXT(" 0x%x/*ZEROLENGTH*"), pnod->res.id));
else if (pnod->res.len == 1) OUTPUT((TEXT(" 0x%x"), pnod->res.id));
else OUTPUT((TEXT(" 0x%x-0x%x"), pnod->res.id, pnod->res.id + pnod->res.len - 1));
pnod = pnod->pNext;
}
}
OUTPUT((TEXT("\n")));
}
void ResourceDumpAll (void)
{
ResourceDomain *pdom;
EnterCriticalSection(&gcsIORM);
pdom = g_DomainList;
if (pdom == NULL)
OUTPUT((TEXT("* There are no resource domains defined. *\n")));
while (pdom) {
ResourceDump(pdom);
if (pdom = pdom->pNext)
OUTPUT((TEXT("\n")));
}
LeaveCriticalSection(&gcsIORM);
}
#endif
#ifdef UNIT_TEST
main() {
char buf[50], c;
DWORD r, a[3];
while (1) {
printf("RES> "); fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) == NULL) exit(0);
r = sscanf(buf, "%c %d %d %d", &c, &a[0], &a[1], &a[2]);
if (r < 1) continue;
switch (tolower(c)) {
case 'd':
if (r == 1)
ResourceDumpAll();
else {
ResourceDomain *d = FindDomain(a[0]);
if (d == NULL) OUTPUT((TEXT("* No resource domain with id %u. *\n"), a[0]));
else ResourceDump(d);
}
break;
case 'c':
if (r < 4) {
OUTPUT((TEXT("* Create resource domain: c resid min cnt *\n")));
continue;
}
if (ResourceCreateList(a[0], a[1], a[2]))
OUTPUT((TEXT("Created.\n")));
else
OUTPUT((TEXT("FAILED.\n")));
break;
case 'g':
if (r < 3) {
OUTPUT((TEXT("* Request resources: g resid id [len] *\n")));
continue;
}
if (r < 4)
a[2] = 1;
if (ResourceRequest(a[0], a[1], a[2]))
OUTPUT((TEXT("Granted.\n")));
else
OUTPUT((TEXT("DENIED.\n")));
break;
case 'f':
if (r < 3) {
OUTPUT((TEXT("* Release resources: f resid id [len] *\n")));
continue;
}
if (r < 4)
a[2] = 1;
if (ResourceRelease(a[0], a[1], a[2]))
OUTPUT((TEXT("Released.\n")));
else
OUTPUT((TEXT("DENIED.\n")));
break;
case 's':
if (r < 3) {
OUTPUT((TEXT("* Make resources shareable: s resid id [len] *\n")));
continue;
}
if (r < 4)
a[2] = 1;
if (IORM_ResourceMarkAsShareable(a[0], a[1], a[2], TRUE))
OUTPUT((TEXT("Done.\n")));
else
OUTPUT((TEXT("FAILED.\n")));
break;
case '$':
exit(0);
case '?': case 'h':
OUTPUT((TEXT("c=create g=request f=release s=share d=dump $=exit\n")));
break;
}
}
}
#endif /* UNIT_TEST */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -