Added a hook to capture when aaApi_DocumentSelectDlg checks out a document, selecting a file that is a parent in a logical set
in AAPOSTHOOK + AAHOOK_CHECKOUT_DOCUMENT , where param2 == AAOPER_DOC_CHECKOUT
lProjectId is always -7
lDocumentId changes as if it’s the set number (didn’t check)
//paramType is param2, arg is param 1 from aaApiHook if (AAOPER_DOC_CHECKOUT == paramType && arg != 0) { const AADOCTODIR_PARAM *data = reinterpret_cast<const AADOCTODIR_PARAM*>(arg); if (data != nullptr && data->lptstrFileName != nullptr) { pwDoc.setPath(data->lptstrFileName); if (data->lpDocuments != nullptr && data->lCount > 0) { pwDoc.setProjectId(data->lpDocuments->lProjectId); //incorrect value pwDoc.setDocumentId(data->lpDocuments->lDocumentId); //incorrect value } } }
seems when the projectID is -7, the documentID is a setID
just found AADMS_SETPROJECT_ID is -7, wondering if there are other values I need to check
static void getPwDocumentFromParam(PwDocument &pwDoc, LPAADOC_ITEM item) { if (item != nullptr && AADMS_IS_VALID_PROJECT_ID(item->lProjectId)) { if (item->lProjectId == AADMS_SETPROJECT_ID) { LONG projId = -1, docId = -1; if (aaApi_GetSetMaster(item->lDocumentId, &projId, &docId)) { pwDoc.setProjectId(projId); pwDoc.setDocumentId(docId); //todo validate with filename? } } else { pwDoc.setProjectId(item->lProjectId); pwDoc.setDocumentId(item->lDocumentId); } } }
Answer Verified By: Daniel Marcotte
Daniel,
I'm not sure what you are attempting to do when you ask "if there are other values I need to check?"
Looking at the code you first posted, and indicated that the values returned are not valid, here is a sample similar to what I use in the PW SDK training class, and it returns valid values for AADOCTODIR_PARAM. However, when that structure is used by the hook mechanism, not all values in the structure are actually populated. It does populate the structure with valid project and document Ids, but not the file name buffer. You have select the document and get the filename from the buffer:
// MarcotteHookTest.cpp : Defines the initialization routines for the DLL. // #include "stdafx.h" #include "MarcotteHookTest.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // //TODO: If this DLL is dynamically linked against the MFC DLLs, // any functions exported from this DLL which call into // MFC must have the AFX_MANAGE_STATE macro added at the // very beginning of the function. // // For example: // // extern "C" BOOL PASCAL EXPORT ExportedFunction() // { // AFX_MANAGE_STATE(AfxGetStaticModuleState()); // // normal function body here // } // // It is very important that this macro appear in each // function, prior to any calls into MFC. This means that // it must appear as the first statement within the // function, even before any object variable declarations // as their constructors may generate calls into the MFC // DLL. // // Please see MFC Technical Notes 33 and 58 for additional // details. // // CMarcotteHookTestApp BEGIN_MESSAGE_MAP(CMarcotteHookTestApp, CWinApp) END_MESSAGE_MAP() // CMarcotteHookTestApp construction CMarcotteHookTestApp::CMarcotteHookTestApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance } // The one and only CMarcotteHookTestApp object CMarcotteHookTestApp theApp; // CMarcotteHookTestApp initialization LONG AAAPIHOOK Hook_CheckOutDocument ( LONG hookId, /* i Hook Identifier */ LONG hookType, /* i Hook Function Type */ AAPARAM aParam1, /* i Parameter for Hook Function */ AAPARAM aParam2, /* i Parameter for Hook Function */ AARESULT* pResult /* o Return code of the hook function */ ) { TRACE(L"Hook_CheckOutDocument_Pre() called...\n"); /****************************************************************************** Check aParam2 - we only care about AAOPER_DOC_CHECKOUT so return AAHOOK_SUCCESS for anything else *******************************************************************************/ if (aParam2 != AAOPER_DOC_CHECKOUT) { return AAHOOK_SUCCESS; } /****************************************************************************** Define variable to point to aParam1 for easier use Lookup AAHOOK_CHECKOUT_DOCUMENT in help *******************************************************************************/ AADOCTODIR_PARAM const* pDocDirParam = reinterpret_cast<AADOCTODIR_PARAM const*> (aParam1); /****************************************************************************** The project id, document id, and file name are in the aParam1 structure. pDocDirParam->lpDocuments->lProjectId pDocDirParam->lpDocuments->lDocumentId pDocDirParam->lptstrFileName *******************************************************************************/ TRACE(L"\n Project Id: %d\n", pDocDirParam->lpDocuments->lProjectId); TRACE(L"\nDocument Id: %d\n", pDocDirParam->lpDocuments->lDocumentId); TRACE(L"\n File Name: %s\n", pDocDirParam->lptstrFileName); CString strMsg; strMsg.Format(L" Project Id: %d\nDocument Id: %d\n File Name: %s", pDocDirParam->lpDocuments->lProjectId, pDocDirParam->lpDocuments->lDocumentId, pDocDirParam->lptstrFileName); aaApi_MessageBox(strMsg, MB_OK); LONG lRetCode = aaApi_SelectDocument( pDocDirParam->lpDocuments->lProjectId, pDocDirParam->lpDocuments->lDocumentId); if (lRetCode <= 0) { // error return AAHOOK_ERROR; } strMsg.Format(L" Project Id: %d\nDocument Id: %d\n File Name: %s", pDocDirParam->lpDocuments->lProjectId, pDocDirParam->lpDocuments->lDocumentId, aaApi_GetDocumentStringProperty(DOC_PROP_FILENAME, 0)); aaApi_MessageBox(strMsg, MB_OK); return AAHOOK_SUCCESS; // means action was preformed... } BOOL CMarcotteHookTestApp::InitInstance() { CWinApp::InitInstance(); aaApi_AddHook(AAHOOK_CHECKOUT_DOCUMENT, AAACTIONHOOK, Hook_CheckOutDocument); return TRUE; } BOOL CMarcotteHookTestApp::ExitInstance() { aaApi_RemoveHook(AAHOOK_CHECKOUT_DOCUMENT, AAACTIONHOOK, Hook_CheckOutDocument); return CWinApp::ExitInstance(); } extern "C" LONG CustomInitialize ( ULONG ulMask, /* i Application Mask */ LPVOID lpReserved /* i Reserved (must be NULL) */ ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); TRACE(L"\nCustomInitialize() called...\n"); return IDOK; }
My test code returns this for just the structure:
And this after I select the document and get the file name from the buffer: