STATIC VOID FreeINI(PXINI pXIni) // in: profile opened with xprfOpenProfile { if (pXIni) { PLISTNODE pAppNode = lstQueryFirstNode(&pXIni->llApps); while (pAppNode) { PXINIAPPDATA pAppDataThis = (PXINIAPPDATA)pAppNode->pItemData; FreeApp(pAppDataThis); pAppNode = pAppNode->pNext; } lstClear(&pXIni->llApps); free(pXIni); } }
STATIC VOID FreeApp(PXINIAPPDATA pAppDataThis) { PLISTNODE pKeyNode = lstQueryFirstNode(&pAppDataThis->llKeys); while (pKeyNode) { PXINIKEYDATA pKeyDataThis = (PXINIKEYDATA)pKeyNode->pItemData; FreeKey(pKeyDataThis); pKeyNode = pKeyNode->pNext; } if (pAppDataThis->pszAppName) free(pAppDataThis->pszAppName); lstClear(&pAppDataThis->llKeys); free(pAppDataThis); }
STATIC APIRET FindKey(PXINIAPPDATA pAppData, const char *pcszKey, PXINIKEYDATA *ppKeyData) { PLISTNODE pKeyNode = lstQueryFirstNode(&pAppData->llKeys); while (pKeyNode) { PXINIKEYDATA pKeyDataThis = (PXINIKEYDATA)pKeyNode->pItemData; if (!strcmp(pKeyDataThis->pszKeyName, pcszKey)) { *ppKeyData = pKeyDataThis; return NO_ERROR; } pKeyNode = pKeyNode->pNext; } return PRFERR_INVALID_KEY_NAME; }
STATIC APIRET FindApp(PXINI pXIni, // in: profile opened with xprfOpenProfile const char *pcszApp, PXINIAPPDATA *ppAppData) { PLISTNODE pAppNode = lstQueryFirstNode(&pXIni->llApps); while (pAppNode) { PXINIAPPDATA pAppDataThis = (PXINIAPPDATA)pAppNode->pItemData; if (!strcmp(pAppDataThis->pszAppName, pcszApp)) { *ppAppData = pAppDataThis; return NO_ERROR; } pAppNode = pAppNode->pNext; } return PRFERR_INVALID_APP_NAME; }
BOOL MoveCurrentDesktop(HAB hab, LONG dx, // in: X delta LONG dy) // in: Y delta { BOOL brc = FALSE; LONG cxEach = G_pHookData->szlEachDesktopFaked.cx, cDesktopsX = G_pHookData->PagerConfig.cDesktopsX, xCurrent = G_pHookData->ptlCurrentDesktop.x, xLimit = cDesktopsX * cxEach, xNew = xCurrent - dx; LONG cyEach = G_pHookData->szlEachDesktopFaked.cy, cDesktopsY = G_pHookData->PagerConfig.cDesktopsY, yCurrent = G_pHookData->ptlCurrentDesktop.y, yLimit = cDesktopsY * cyEach, yNew = yCurrent - dy; ULONG flPager = G_pHookData->PagerConfig.flPager; // bump X delta if (dx) { if (xNew < 0) { if (flPager & PGRFL_WRAPAROUND) dx = -((cDesktopsX - 1) * cxEach); else dx = 0; } else if ((xNew + cxEach) > xLimit) { if (flPager & PGRFL_WRAPAROUND) dx = (cDesktopsX - 1) * cxEach; else dx = 0; } } // bump Y delta if (dy) { if (yNew < 0) { if (flPager & PGRFL_WRAPAROUND) dy = -((cDesktopsY - 1) * cyEach); else dy = 0; } else if ((yNew + cyEach) > yLimit) { if (flPager & PGRFL_WRAPAROUND) dy = (cDesktopsY - 1) * cyEach; else dy = 0; } } if ( (dx) || (dy) ) { BOOL fAnythingMoved = TRUE; PSWP paswpNew = NULL; ULONG cSwpNewUsed = 0; HWND *pahwndNoMoveWithOwner = NULL; ULONG cNoMoveWithOwner = 0; if (pgrLockWinlist()) { // allocate an array of SWP entries for moving all windows // at once... we'll allocate one SWP entry for each item // on the wininfo list, but we'll probably not use them // all. cSwpNewUsed will be incremented for each item that's // actually used. While we build that list, we check the // internal daemon winlist for sanity, since we sometimes // do not pick up all relevant changes such as "parent changed", // which will block the WinSetMultWindowPos otherwise. ULONG cWinInfos, cbSwpNew, cbNoMoveWithOwner; if ( (cWinInfos = lstCountItems(&G_llWinInfos)) && (cbSwpNew = cWinInfos * sizeof(SWP)) && (cbNoMoveWithOwner = cWinInfos * sizeof(HWND)) // allocate array of SWPs WinSetMultWindowPos: && (paswpNew = (PSWP)malloc(cbSwpNew)) // allocate array of HWNDs for which we // might disable FS_NOMOVEWITHOWNER: && (pahwndNoMoveWithOwner = (HWND*)malloc(cbNoMoveWithOwner)) ) { PLISTNODE pNode, pNext; // now go thru all windows on the main list and copy them // to the move list, if necessary for (pNode = lstQueryFirstNode(&G_llWinInfos); pNode; pNode = pNext) { PXWININFO pEntryThis = (PXWININFO)pNode->pItemData; pNext = pNode->pNext; if ( (!WinQueryWindowPos(pEntryThis->data.swctl.hwnd, &pEntryThis->data.swp)) // check if it's still a desktop child (fixes #524) || (WinQueryWindow(pEntryThis->data.swctl.hwnd,QW_PARENT) != G_pHookData->hwndPMDesktop) ) // window no longer valid: // remove from the list NOW WinPostMsg(G_pHookData->hwndDaemonObject, XDM_WINDOWCHANGE, (MPARAM)pEntryThis->data.swctl.hwnd, (MPARAM)WM_DESTROY); else { BOOL fRefreshThis = FALSE; // fix outdated minimize/maximize/hide flags if ( (pEntryThis->data.bWindowType == WINDOW_MINIMIZE) && (!(pEntryThis->data.swp.fl & SWP_MINIMIZE)) ) // no longer minimized: fRefreshThis = TRUE; else if ( (pEntryThis->data.bWindowType == WINDOW_MAXIMIZE) && (!(pEntryThis->data.swp.fl & SWP_MAXIMIZE)) ) // no longer minimized: fRefreshThis = TRUE; if (pEntryThis->data.bWindowType == WINDOW_NORMAL) { if (pEntryThis->data.swp.fl & SWP_HIDE) fRefreshThis = TRUE; else if (pEntryThis->data.swp.fl & SWP_MINIMIZE) // now minimized: pEntryThis->data.bWindowType = WINDOW_MINIMIZE; else if (pEntryThis->data.swp.fl & SWP_MAXIMIZE) // now maximized: pEntryThis->data.bWindowType = WINDOW_MAXIMIZE; } if (fRefreshThis) { if (!pgrGetWinData(&pEntryThis->data, TRUE)) // quick check, we already have most data { // window no longer valid: // remove from the list NOW // V0.9.15 (2001-09-14) [umoeller] WinPostMsg(G_pHookData->hwndDaemonObject, XDM_WINDOWCHANGE, (MPARAM)pEntryThis->data.swctl.hwnd, (MPARAM)WM_DESTROY); // update pEntryThis so that we don't try to // move it later // V0.9.19 (2002-04-04) [lafaix] pEntryThis = NULL; } } // move the window if it is not sticky, minimized, // hidden, or invisible // V0.9.19 (2002-04-04) [lafaix] if ( (pEntryThis) && ( (pEntryThis->data.bWindowType == WINDOW_MAXIMIZE) || ( (pEntryThis->data.bWindowType == WINDOW_NORMAL) && (!(pEntryThis->data.swp.fl & SWP_HIDE)) ) || ( (pEntryThis->data.bWindowType == WINDOW_NIL) && (!(pEntryThis->data.swp.fl & SWP_HIDE)) && (WinQueryWindowULong(pEntryThis->data.swctl.hwnd, QWL_STYLE) & WS_VISIBLE) ) ) ) { // OK, window to be moved: // default flags ULONG fl = SWP_MOVE | SWP_NOADJUST; // SWP_NOADJUST is required or the windows // will end up in the middle of nowhere PSWP pswpNewThis = &paswpNew[cSwpNewUsed]; // we have queried the window pos above memcpy(pswpNewThis, &pEntryThis->data.swp, sizeof(SWP)); pswpNewThis->hwnd = pEntryThis->data.swctl.hwnd; // add the delta for moving pswpNewThis->x += dx; pswpNewThis->y += dy; pswpNewThis->fl = fl; // use next entry in SWP array cSwpNewUsed++; // set FS_NOMOVEWITHOWNER temporarily // (moved this down V1.0.3 (2004-03-11) [umoeller] if ( (!strcmp(pEntryThis->data.szClassName, "#1") && (!(WinQueryWindowULong(pEntryThis->data.swctl.hwnd, QWL_STYLE) & FS_NOMOVEWITHOWNER)) ) ) { pahwndNoMoveWithOwner[cNoMoveWithOwner++] = pEntryThis->data.swctl.hwnd; WinSetWindowBits(pEntryThis->data.swctl.hwnd, QWL_STYLE, FS_NOMOVEWITHOWNER, FS_NOMOVEWITHOWNER); } } // end if ( (pEntryThis->bWindowType == WINDOW_MAXIMIZE)... } } // end while (pNode) } // end if (paswpNew = (PSWP)malloc(cbSwpNew))) etc. if (paswpNew) { if (cSwpNewUsed) { // disable message processing in the hook if (pgrLockHook(__FILE__, __LINE__, __FUNCTION__)) { // now set all windows at once, this saves a lot of // repainting... fAnythingMoved = WinSetMultWindowPos(hab, paswpNew, cSwpNewUsed); pgrUnlockHook(); } } // clean up SWP array free(paswpNew); } // if (paswpNew) // unset FS_NOMOVEWITHOWNER for the windows where we set it above while (cNoMoveWithOwner) WinSetWindowBits(pahwndNoMoveWithOwner[--cNoMoveWithOwner], QWL_STYLE, 0, FS_NOMOVEWITHOWNER); pgrUnlockWinlist(); } if (pahwndNoMoveWithOwner) free(pahwndNoMoveWithOwner); if (fAnythingMoved) { G_pHookData->ptlCurrentDesktop.x -= dx; G_pHookData->ptlCurrentDesktop.y -= dy; WinPostMsg(G_pHookData->hwndPagerClient, PGRM_REFRESHCLIENT, (MPARAM)FALSE, 0); if (flPager & PGRFL_FLASHTOTOP) WinSetWindowPos(G_pHookData->hwndPagerFrame, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER | SWP_SHOW | SWP_RESTORE); brc = TRUE; } } return brc; }
APIRET xprfQueryProfileData(PXINI pXIni, // in: profile opened with xprfOpenProfile PCSZ pszAppName, // in: application name PCSZ pszKeyName, // in: key name or NULL PVOID pBuffer, // in: buffer to receive data PULONG pulBufferMax) // in: buffer size, out: size of written data { APIRET arc = NO_ERROR; ULONG ulDataLen = 0; if (!pszAppName) { PLISTNODE pAppNode = lstQueryFirstNode(&pXIni->llApps); PBYTE pbTarget = (PBYTE)pBuffer; ULONG cbCopied = 0; while (pAppNode) { PXINIAPPDATA pAppDataThis = (PXINIAPPDATA)pAppNode->pItemData; ULONG cbThis = strlen(pAppDataThis->pszAppName) + 1; if (cbCopied + cbThis > *pulBufferMax) break; else { memcpy(pbTarget + cbCopied, pAppDataThis->pszAppName, cbThis); cbCopied += cbThis; } pAppNode = pAppNode->pNext; } // extra byte for terminating extra null pbTarget[cbCopied] = '\0'; ulDataLen = cbCopied; // PMREF says terminating null is not counted } else { // app specified: PXINIAPPDATA pAppData; if (!(arc = FindApp(pXIni, pszAppName, &pAppData))) { // app exists: if (!pszKeyName) { // app != NULL, but key == NULL: // return size of keys list PLISTNODE pKeyNode = lstQueryFirstNode(&pAppData->llKeys); PBYTE pbTarget = (PBYTE)pBuffer; ULONG cbCopied = 0; while (pKeyNode) { PXINIKEYDATA pKeyDataThis = (PXINIKEYDATA)pKeyNode->pItemData; ULONG cbThis = strlen(pKeyDataThis->pszKeyName) + 1; if (cbCopied + cbThis > *pulBufferMax) break; else { memcpy(pbTarget + cbCopied, pKeyDataThis->pszKeyName, cbThis); cbCopied += cbThis; } pKeyNode = pKeyNode->pNext; } // extra byte for terminating extra null pbTarget[cbCopied] = '\0'; ulDataLen = cbCopied; // PMREF says terminating null is not counted } else { // both app and key specified: PXINIKEYDATA pKeyData; if (!(arc = FindKey(pAppData, pszKeyName, &pKeyData))) { ulDataLen = __min(pKeyData->cbData, *pulBufferMax); memcpy(pBuffer, pKeyData->pbData, ulDataLen); } } } } if (pulBufferMax) *pulBufferMax = ulDataLen; return arc; }
APIRET xprfQueryProfileSize(PXINI pXIni, // in: profile opened with xprfOpenProfile PCSZ pszAppName, // in: application name or NULL PCSZ pszKeyName, // in: key name or NULL PULONG pulDataLen) // out: size of requested data { APIRET arc = NO_ERROR; ULONG ulDataLen = 0; if (!pszAppName) { PLISTNODE pAppNode = lstQueryFirstNode(&pXIni->llApps); while (pAppNode) { PXINIAPPDATA pAppDataThis = (PXINIAPPDATA)pAppNode->pItemData; ulDataLen += strlen(pAppDataThis->pszAppName) + 1; pAppNode = pAppNode->pNext; } // extra byte for terminating extra null ++ulDataLen; } else { // app specified: PXINIAPPDATA pAppData; if (!(arc = FindApp(pXIni, pszAppName, &pAppData))) { // app exists: if (!pszKeyName) { // app != NULL, but key == NULL: // return size of keys list PLISTNODE pKeyNode = lstQueryFirstNode(&pAppData->llKeys); while (pKeyNode) { PXINIKEYDATA pKeyDataThis = (PXINIKEYDATA)pKeyNode->pItemData; ulDataLen += strlen(pKeyDataThis->pszKeyName) + 1; pKeyNode = pKeyNode->pNext; } // extra byte for terminating extra null ++ulDataLen; } else { // both app and key specified: PXINIKEYDATA pKeyData; if (!(arc = FindKey(pAppData, pszKeyName, &pKeyData))) ulDataLen = pKeyData->cbData; } } } if (pulDataLen) *pulDataLen = ulDataLen; return arc; }
STATIC APIRET WriteINI(PXINI pXIni) // in: profile opened with xprfOpenProfile { APIRET arc = NO_ERROR; ULONG ulTotalFileSize = sizeof(INIFILE_HEADER); ULONG ulSet = 0; PBYTE pbData2Write = NULL; // check how much memory we'll need: // one INIFILE_HEADER // + for each app: one INIFILE_APP plus app name length // + for each key: one INIFILE_KEY plus key name length plus data length // go thru all apps PLISTNODE pAppNode = lstQueryFirstNode(&pXIni->llApps); while (pAppNode) { PLISTNODE pKeyNode; PXINIAPPDATA pAppDataThis = (PXINIAPPDATA)pAppNode->pItemData; // one INIFILE_APP plus app name length for each app ulTotalFileSize += sizeof(INIFILE_APP) + strlen(pAppDataThis->pszAppName) + 1; // null terminator // for each app, go thru all keys pKeyNode = lstQueryFirstNode(&pAppDataThis->llKeys); while (pKeyNode) { PXINIKEYDATA pKeyDataThis = (PXINIKEYDATA)pKeyNode->pItemData; ulTotalFileSize += sizeof(INIFILE_KEY) + strlen(pKeyDataThis->pszKeyName) + pKeyDataThis->cbData + 1; // null terminator pKeyNode = pKeyNode->pNext; } pAppNode = pAppNode->pNext; } // allocate buffer for total size if (pbData2Write = (PBYTE)malloc(ulTotalFileSize)) { // set header in buffer PINIFILE_HEADER pHeader = (PINIFILE_HEADER)pbData2Write; // pointer into buffer for current write // (used below) ULONG ulCurOfs = sizeof(INIFILE_HEADER); // 1) set up header pHeader->magic = 0xFFFFFFFF; if (lstCountItems(&pXIni->llApps)) // we have any applications: pHeader->offFirstApp = sizeof(INIFILE_HEADER); // offset of first application in file else // empty INI file: pHeader->offFirstApp = 0; pHeader->lenFile = ulTotalFileSize; pHeader->filler1 = 0; pHeader->filler2 = 0; // 2) for-all-applications loop pAppNode = lstQueryFirstNode(&pXIni->llApps); while (pAppNode) { PXINIAPPDATA pAppDataThis = (PXINIAPPDATA)pAppNode->pItemData; ULONG cbAppName = strlen(pAppDataThis->pszAppName) + 1; // layout of application entry in file: // -- struct PINIFILE_APP (ulCurOfs right now) // -- application name (null-terminated) // -- INIFILE_KEY 1 // -- INIFILE_KEY 2 ... // -- next struct PINIFILE_APP // make pointer to application entry PINIFILE_APP pIniAppCurrent = (PINIFILE_APP)(pbData2Write + ulCurOfs); // write out application entry // pIniAppCurrent->offNextApp = 0; // pIniAppCurrent->offFirstKeyInApp = ulCurOfs + cbAppName; pIniAppCurrent->filler1 = 0; pIniAppCurrent->lenAppName = pIniAppCurrent->_lenAppName = cbAppName; // set offset to application name: put this right after the application ulCurOfs += sizeof(INIFILE_APP); pIniAppCurrent->offAppName = ulCurOfs; // write app name (null-terminated) memcpy(pbData2Write + ulCurOfs, pAppDataThis->pszAppName, cbAppName); ulCurOfs += cbAppName; // ulCurOfs points to INIFILE_KEY entry now if (pAppDataThis->cKeys) { // we have keys: PLISTNODE pKeyNode = lstQueryFirstNode(&pAppDataThis->llKeys); pIniAppCurrent->offFirstKeyInApp = ulCurOfs; // 3) for-all-keys loop per application while (pKeyNode) { PXINIKEYDATA pKeyDataThis = (PXINIKEYDATA)pKeyNode->pItemData; ULONG cbKeyName = strlen(pKeyDataThis->pszKeyName) + 1; PINIFILE_KEY pIniKeyCurrent = (PINIFILE_KEY)(pbData2Write + ulCurOfs); pIniKeyCurrent->filler1 = 0; ulCurOfs += sizeof(INIFILE_KEY); // has offset to key name now // a) key name pIniKeyCurrent->lenKeyName = pIniKeyCurrent->_lenKeyName = cbKeyName; pIniKeyCurrent->offKeyName = ulCurOfs; memcpy(pbData2Write + ulCurOfs, pKeyDataThis->pszKeyName, cbKeyName); ulCurOfs += cbKeyName; // has offset to data now // b) data pIniKeyCurrent->lenKeyData = pIniKeyCurrent->_lenKeyData = pKeyDataThis->cbData; pIniKeyCurrent->offKeyData = ulCurOfs; memcpy(pbData2Write + ulCurOfs, pKeyDataThis->pbData, pKeyDataThis->cbData); ulCurOfs += pKeyDataThis->cbData; // points to after all key data now; // this receives either the next key/data block // or the next application or nothing // ofs of next key: if (pKeyNode->pNext) pIniKeyCurrent->offNextKeyInApp = ulCurOfs; else // last key: pIniKeyCurrent->offNextKeyInApp = 0; pKeyNode = pKeyNode->pNext; } // ulCurOfs points to after the last keys entry now } else // no keys: pIniAppCurrent->offFirstKeyInApp = 0; // done with keys (there may be none!); // now set offset to next app in current application if (pAppNode->pNext) pIniAppCurrent->offNextApp = ulCurOfs; else // this was the last one: pIniAppCurrent->offNextApp = 0; // next app pAppNode = pAppNode->pNext; } // write out everything if (!(arc = DosSetFilePtr(pXIni->hFile, 0, FILE_BEGIN, &ulSet))) { ULONG cbWritten = 0; if (!(arc = DosWrite(pXIni->hFile, pbData2Write, ulTotalFileSize, &cbWritten))) { if (!(arc = DosSetFileSize(pXIni->hFile, ulTotalFileSize))) ; } } free(pbData2Write); } return arc; }